diff -Nru shotwell-0.11.91/chkver shotwell-0.11.92/chkver --- shotwell-0.11.91/chkver 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/chkver 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/bash # -# Copyright 2009-2011 Yorba Foundation +# Copyright 2009-2012 Yorba Foundation # # This software is licensed under the GNU LGPL (version 2.1 or later). # See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/configure shotwell-0.11.92/configure --- shotwell-0.11.91/configure 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/configure 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright 2009-2011 Yorba Foundation +# Copyright 2009-2012 Yorba Foundation # # This software is licensed under the GNU LGPL (version 2.1 or later). # See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/debian/changelog shotwell-0.11.92/debian/changelog --- shotwell-0.11.91/debian/changelog 2012-01-12 10:59:45.000000000 +0000 +++ shotwell-0.11.92/debian/changelog 2012-02-21 03:00:13.000000000 +0000 @@ -1,3 +1,9 @@ +shotwell (0.11.92-0ubuntu1) precise; urgency=low + + * New upstream release + + -- Robert Ancell Tue, 21 Feb 2012 13:52:58 +1100 + shotwell (0.11.91-0ubuntu2) precise; urgency=low * debian/control: use the correct liblaunchpad-integration version diff -Nru shotwell-0.11.91/icons/straighten.svg shotwell-0.11.92/icons/straighten.svg --- shotwell-0.11.91/icons/straighten.svg 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/icons/straighten.svg 2012-02-20 22:59:53.000000000 +0000 @@ -0,0 +1,1051 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru shotwell-0.11.91/INSTALL shotwell-0.11.92/INSTALL --- shotwell-0.11.91/INSTALL 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/INSTALL 2012-02-20 20:47:27.000000000 +0000 @@ -23,5 +23,5 @@ menu under Graphics or Photography. - Copyright 2009-2011 Yorba Foundation + Copyright 2009-2012 Yorba Foundation diff -Nru shotwell-0.11.91/libraw-config shotwell-0.11.92/libraw-config --- shotwell-0.11.91/libraw-config 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/libraw-config 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/bash # -# Copyright 2010-2011 Yorba Foundation +# Copyright 2010-2012 Yorba Foundation # # This software is licensed under the GNU LGPL (version 2.1 or later). # See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/Makefile shotwell-0.11.92/Makefile --- shotwell-0.11.91/Makefile 2012-01-06 01:32:59.000000000 +0000 +++ shotwell-0.11.92/Makefile 2012-02-21 00:55:38.000000000 +0000 @@ -1,7 +1,7 @@ PROGRAM = shotwell PROGRAM_THUMBNAILER = shotwell-video-thumbnailer -VERSION = 0.11.91 +VERSION = 0.11.92 GETTEXT_PACKAGE = $(PROGRAM) BUILD_ROOT = 1 @@ -9,7 +9,7 @@ VALAC := valac endif VALAC_VERSION := `$(VALAC) --version | awk '{print $$2}'` -MIN_VALAC_VERSION := 0.15.0 +MIN_VALAC_VERSION := 0.15.1 INSTALL_PROGRAM := install INSTALL_DATA := install -m 644 @@ -33,7 +33,7 @@ LOCAL_LANG_DIR=locale-langpack SYSTEM_LANG_DIR := $(DESTDIR)$(PREFIX)/share/locale -VALAFLAGS := -g --enable-checking --thread --fatal-warnings $(USER_VALAFLAGS) +VALAFLAGS := -g --enable-checking --thread --fatal-warnings --enable-deprecated $(USER_VALAFLAGS) ifdef UNITY_SUPPORT VALAFLAGS := $(VALAFLAGS) --define UNITY_SUPPORT endif @@ -108,14 +108,14 @@ shotwell-video-thumbnailer.vala VAPI_FILES = \ - gdk-3.0.vapi \ - unique-3.0.vapi \ - webkitgtk-3.0.vapi \ - libexif.vapi \ - libgphoto2.vapi \ ExtendedPosix.vapi \ + hmac-glib.vapi \ LConv.vapi \ - libraw.vapi + libexif.vapi \ + libgphoto2.vapi \ + libraw.vapi \ + unique-3.0.vapi \ + webkitgtk-3.0.vapi RESOURCE_FILES = \ collection.ui \ @@ -194,6 +194,7 @@ shotwell-street.jpg \ shotwell.svg \ sprocket.png \ + straighten.svg \ three-star-filter-plus.svg \ three-stars.svg \ two-star-filter-plus.svg \ @@ -305,9 +306,9 @@ # should be added to this list EXT_PKG_VERSIONS = \ gee-1.0 >= 0.5.0 \ - gexiv2 >= 0.2.0 \ + gexiv2 >= 0.3.90 \ gio-unix-2.0 >= 2.20 \ - glib-2.0 >= 2.26.0 \ + glib-2.0 >= 2.30.0 \ gmodule-2.0 >= 2.24.0 \ gstreamer-0.10 >= 0.10.28 \ gstreamer-base-0.10 >= 0.10.28 \ diff -Nru shotwell-0.11.91/misc/org.yorba.shotwell.gschema.xml shotwell-0.11.92/misc/org.yorba.shotwell.gschema.xml --- shotwell-0.11.91/misc/org.yorba.shotwell.gschema.xml 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/misc/org.yorba.shotwell.gschema.xml 2012-02-20 20:47:27.000000000 +0000 @@ -318,13 +318,19 @@ - + "" - auth token + OAuth Access Phase Token The authorization token for the currently logged in Flickr user, if any - - + + + "" + OAuth Access Phase Token Secret + The cryptographic secret used to sign requests against the authorization token for the currently logged in Flickr user, if any + + + "" username The user name of the currently logged in Flickr user, if any @@ -383,6 +389,14 @@ + + + "" + last used import service + A numeric code representing the last service from which photos were imported + + + -1 @@ -494,6 +508,12 @@ True if the Yandex.Fotki publishing plugin is enabled, false otherwise + + true + enable F-Spot import plugin + True if the F-Spot import plugin is enabled, false otherwise + + true enable slideshow crumble transition diff -Nru shotwell-0.11.91/misc/shotwell.convert shotwell-0.11.92/misc/shotwell.convert --- shotwell-0.11.91/misc/shotwell.convert 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/misc/shotwell.convert 2012-02-20 20:47:27.000000000 +0000 @@ -75,16 +75,12 @@ transitions-slide = /apps/shotwell/plugins/org.yorba.shotwell.transitions.slide/enabled [org.yorba.shotwell.sharing.facebook] -session-key = /apps/shotwell/sharing/facebook/session_key -session-secret = /apps/shotwell/sharing/facebook/session_secret uid = /apps/shotwell/sharing/facebook/uid user-name = /apps/shotwell/sharing/facebook/user_name default-size = /apps/shotwell/sharing/facebook/default_size [org.yorba.shotwell.sharing.flickr] -auth-token = /apps/shotwell/sharing/flickr/auth_token default-size = /apps/shotwell/sharing/flickr/default_size -username = /apps/shotwell/sharing/flickr/username visibility = /apps/shotwell/sharing/flickr/visibility [org.yorba.shotwell.sharing.picasa] diff -Nru shotwell-0.11.91/plugins/common/Resources.vala shotwell-0.11.92/plugins/common/Resources.vala --- shotwell-0.11.91/plugins/common/Resources.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/common/Resources.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/plugins/common/RESTSupport.vala shotwell-0.11.92/plugins/common/RESTSupport.vala --- shotwell-0.11.91/plugins/common/RESTSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/common/RESTSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,11 +1,10 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. */ extern Soup.Message soup_form_request_new_from_multipart(string uri, Soup.Multipart multipart); -extern void qsort(void *p, size_t num, size_t size, GLib.CompareFunc func); namespace Publishing.RESTSupport { @@ -110,6 +109,15 @@ return strcmp(arg1->key, arg2->key); } + + public static Argument[] sort(Argument[] inputArray) { + Gee.TreeSet sorted_args = new Gee.TreeSet(Argument.compare); + + foreach (Argument arg in inputArray) + sorted_args.add(arg); + + return sorted_args.to_array(); + } } public class Transaction { @@ -196,20 +204,12 @@ get_endpoint_url()); } - protected Argument[] get_arguments() { + public Argument[] get_arguments() { return arguments; } - protected Argument[] get_sorted_arguments() { - Argument[] sorted_array = new Argument[0]; - - foreach (Argument arg in arguments) - sorted_array += arg; - - qsort(sorted_array, sorted_array.length, sizeof(Argument), - (CompareFunc) Argument.compare); - - return sorted_array; + public Argument[] get_sorted_arguments() { + return Argument.sort(get_arguments()); } protected void set_is_executed(bool is_executed) { @@ -233,7 +233,7 @@ throw err; } - protected HttpMethod get_method() { + public HttpMethod get_method() { return HttpMethod.from_string(message.method); } @@ -299,11 +299,12 @@ // concatenate the REST arguments array into an HTTP formdata string string formdata_string = ""; - foreach (Argument arg in arguments) { - formdata_string = formdata_string + ("%s=%s&".printf(Soup.URI.encode(arg.key, "&"), - Soup.URI.encode(arg.value, "&+"))); + for (int i = 0; i < arguments.length; i++) { + formdata_string += ("%s=%s".printf(arguments[i].key, arguments[i].value)); + if (i < arguments.length - 1) + formdata_string += "&"; } - + // for GET requests with arguments, append the formdata string to the endpoint url after a // query divider ('?') -- but make sure to save the old (caller-specified) endpoint URL // and restore it after the GET so that the underlying Soup message remains consistent @@ -313,12 +314,15 @@ old_url = message.get_uri().to_string(false); url_with_query = get_endpoint_url() + "?" + formdata_string; message.set_uri(new Soup.URI(url_with_query)); + } else { + message.set_request("application/x-www-form-urlencoded", Soup.MemoryUse.COPY, + formdata_string.data); } - message.set_request("application/x-www-form-urlencoded", Soup.MemoryUse.COPY, - formdata_string.data); is_executed = true; + try { + debug("sending message to URI = '%s'", message.get_uri().to_string(false)); send(); } finally { // if old_url is non-null, then restore it diff -Nru shotwell-0.11.91/plugins/common/SqliteSupport.vala shotwell-0.11.92/plugins/common/SqliteSupport.vala --- shotwell-0.11.91/plugins/common/SqliteSupport.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/common/SqliteSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,76 @@ +/* Copyright 2009-2011 Yorba Foundation + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +public errordomain DatabaseError { + ERROR, + BACKING, + MEMORY, + ABORT, + LIMITS, + TYPESPEC +} + +public abstract class DatabaseTable { + + protected static Sqlite.Database db; + + public string table_name = null; + + protected void set_table_name(string table_name) { + this.table_name = table_name; + } + + // This method will throw an error on an SQLite return code unless it's OK, DONE, or ROW, which + // are considered normal results. + protected static void throw_error(string method, int res) throws DatabaseError { + string msg = "(%s) [%d] - %s".printf(method, res, db.errmsg()); + + switch (res) { + case Sqlite.OK: + case Sqlite.DONE: + case Sqlite.ROW: + return; + + case Sqlite.PERM: + case Sqlite.BUSY: + case Sqlite.READONLY: + case Sqlite.IOERR: + case Sqlite.CORRUPT: + case Sqlite.CANTOPEN: + case Sqlite.NOLFS: + case Sqlite.AUTH: + case Sqlite.FORMAT: + case Sqlite.NOTADB: + throw new DatabaseError.BACKING(msg); + + case Sqlite.NOMEM: + throw new DatabaseError.MEMORY(msg); + + case Sqlite.ABORT: + case Sqlite.LOCKED: + case Sqlite.INTERRUPT: + throw new DatabaseError.ABORT(msg); + + case Sqlite.FULL: + case Sqlite.EMPTY: + case Sqlite.TOOBIG: + case Sqlite.CONSTRAINT: + case Sqlite.RANGE: + throw new DatabaseError.LIMITS(msg); + + case Sqlite.SCHEMA: + case Sqlite.MISMATCH: + throw new DatabaseError.TYPESPEC(msg); + + case Sqlite.ERROR: + case Sqlite.INTERNAL: + case Sqlite.MISUSE: + default: + throw new DatabaseError.ERROR(msg); + } + } +} + diff -Nru shotwell-0.11.91/plugins/common/VersionNumber.vala shotwell-0.11.92/plugins/common/VersionNumber.vala --- shotwell-0.11.91/plugins/common/VersionNumber.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/common/VersionNumber.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,50 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace Utils { + +/** + * A class that represents a version number in the form x.y.z and is able to compare + * different versions. + */ +public class VersionNumber : Object, Gee.Comparable { + private int[] version; + + public VersionNumber(int[] version) { + this.version = version; + } + + public VersionNumber.from_string(string str_version, string separator = ".") { + string[] version_items = str_version.split(separator); + this.version = new int[version_items.length]; + for (int i = 0; i < version_items.length; i++) + this.version[i] = int.parse(version_items[i]); + } + + public string to_string() { + string[] version_items = new string[this.version.length]; + for (int i = 0; i < this.version.length; i++) + version_items[i] = this.version[i].to_string(); + return string.joinv(".", version_items); + } + + public int compare_to(VersionNumber other) { + int max_len = ((this.version.length > other.version.length) ? + this.version.length : other.version.length); + int res = 0; + for(int i = 0; i < max_len; i++) { + int this_v = (i < this.version.length ? this.version[i] : 0); + int other_v = (i < other.version.length ? other.version[i] : 0); + res = this_v - other_v; + if (res != 0) + break; + } + return res; + } +} + +} + diff -Nru shotwell-0.11.91/plugins/Makefile.plugin.mk shotwell-0.11.92/plugins/Makefile.plugin.mk --- shotwell-0.11.91/plugins/Makefile.plugin.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/Makefile.plugin.mk 2012-02-20 20:47:27.000000000 +0000 @@ -10,7 +10,9 @@ # NOTE: This file is called from the cwd of each directory, hence the relative paths should be # read as such. +ifndef VALAC VALAC := valac +endif MAKE_FILES := Makefile ../Makefile.plugin.mk ../plugins.mk HEADER_FILES := ../shotwell-plugin-dev-1.0.vapi ../shotwell-plugin-dev-1.0.h \ ../shotwell-plugin-dev-1.0.deps @@ -40,7 +42,7 @@ .stamp: $(SRC_FILES) $(MAKE_FILES) $(HEADER_FILES) $(VALAC) -g --enable-checking --fatal-warnings --save-temps --compile \ - --vapidir=../ $(foreach pkg,$(PKGS),--pkg=$(pkg)) \ + --vapidir=../ $(foreach pkg,$(PKGS),--pkg=$(pkg)) $(foreach pkg,$(CUSTOM_VAPI_PKGS),--pkg=$(pkg)) \ -X -I../.. -X -fPIC \ $(foreach dfn,$(DEFINES),-X $(dfn)) \ $(USER_VALAFLAGS) \ diff -Nru shotwell-0.11.91/plugins/plugins.mk shotwell-0.11.92/plugins/plugins.mk --- shotwell-0.11.91/plugins/plugins.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/plugins.mk 2012-02-20 20:47:27.000000000 +0000 @@ -1,7 +1,8 @@ PLUGINS := \ shotwell-transitions \ - shotwell-publishing + shotwell-publishing \ + shotwell-data-imports PLUGINS_RC := \ plugins/shotwell-publishing/facebook.png \ @@ -17,7 +18,8 @@ plugins/shotwell-publishing-extras/yandex_publish_model.glade \ plugins/shotwell-publishing-extras/piwigo.png \ plugins/shotwell-publishing-extras/piwigo_authentication_pane.glade \ - plugins/shotwell-publishing-extras/piwigo_publishing_options_pane.glade + plugins/shotwell-publishing-extras/piwigo_publishing_options_pane.glade \ + plugins/shotwell-data-imports/f-spot-24.png ALL_PLUGINS := $(PLUGINS) $(EXTRA_PLUGINS) Binary files /tmp/256LWWMZkO/shotwell-0.11.91/plugins/shotwell-data-imports/f-spot-24.png and /tmp/Ihr9_z_29I/shotwell-0.11.92/plugins/shotwell-data-imports/f-spot-24.png differ diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,208 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +private class FSpotBehaviorEntry { + private Utils.VersionNumber version; + private FSpotTableBehavior behavior; + + public FSpotBehaviorEntry(Utils.VersionNumber version, FSpotTableBehavior behavior) { + this.version = version; + this.behavior = behavior; + } + + public Utils.VersionNumber get_version() { + return version; + } + + public FSpotTableBehavior get_behavior() { + return behavior; + } +} + +/** + * A class that consolidates the behavior of all F-Spot tables (apart from meta) + * and is the one place to check whether the database version is supported. + */ +public class FSpotDatabaseBehavior : Object { + // Minimum unsupported version: any database from that version and above + // is not supported as it's too new and support has not been provided + // In practice, the code may work with future versions but this cannot be + // guaranteed as it hasn't been tested so it's probably better to just + // bomb out at that point rather than risk importing incorrect data + public static Utils.VersionNumber MIN_UNSUPPORTED_VERSION = + new Utils.VersionNumber({ 19 }); + private static Gee.Map> behavior_map; + + private FSpotTableBehavior photos_behavior; + private FSpotTableBehavior tags_behavior; + private FSpotTableBehavior photo_tags_behavior; + private FSpotTableBehavior photo_versions_behavior; + private FSpotTableBehavior rolls_behavior; + + public static void create_behavior_map() { + behavior_map = new Gee.HashMap>(); + // photos table + Gee.List photos_list = new Gee.ArrayList(); + // v0-4 + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 0 }), + FSpotPhotosV0Behavior.get_instance() + )); + // v5-6 + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 5 }), + FSpotPhotosV5Behavior.get_instance() + )); + // v7-10 + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 7 }), + FSpotPhotosV7Behavior.get_instance() + )); + // v11-15 + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 11 }), + FSpotPhotosV11Behavior.get_instance() + )); + // v16 + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 16 }), + FSpotPhotosV16Behavior.get_instance() + )); + // v17 + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 17 }), + FSpotPhotosV17Behavior.get_instance() + )); + // v18+ + photos_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 18 }), + FSpotPhotosV18Behavior.get_instance() + )); + behavior_map.set(FSpotPhotosTable.TABLE_NAME, photos_list); + // tags table + Gee.List tags_list = new Gee.ArrayList(); + // v0+ + tags_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 0 }), + FSpotTagsV0Behavior.get_instance() + )); + behavior_map.set(FSpotTagsTable.TABLE_NAME, tags_list); + // photo_tags table + Gee.List photo_tags_list = new Gee.ArrayList(); + // v0+ + photo_tags_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 0 }), + FSpotPhotoTagsV0Behavior.get_instance() + )); + behavior_map.set(FSpotPhotoTagsTable.TABLE_NAME, photo_tags_list); + // photo_versions table + Gee.List photo_versions_list = new Gee.ArrayList(); + // v0-8 + photo_versions_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 0 }), + FSpotPhotoVersionsV0Behavior.get_instance() + )); + // v9-15 + photo_versions_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 9 }), + FSpotPhotoVersionsV9Behavior.get_instance() + )); + // v16 + photo_versions_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 16 }), + FSpotPhotoVersionsV16Behavior.get_instance() + )); + // v17 + photo_versions_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 17 }), + FSpotPhotoVersionsV17Behavior.get_instance() + )); + // v18+ + photo_versions_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 18 }), + FSpotPhotoVersionsV18Behavior.get_instance() + )); + behavior_map.set(FSpotPhotoVersionsTable.TABLE_NAME, photo_versions_list); + // rolls table + Gee.List rolls_list = new Gee.ArrayList(); + // v0-4 + rolls_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 0 }), + FSpotRollsV0Behavior.get_instance() + )); + // v5+ + rolls_list.add(new FSpotBehaviorEntry( + new Utils.VersionNumber({ 5 }), + FSpotRollsV5Behavior.get_instance() + )); + behavior_map.set(FSpotRollsTable.TABLE_NAME, rolls_list); + } + + public static FSpotTableBehavior? find_behavior(string table_name, Utils.VersionNumber version) { + FSpotTableBehavior behavior = null; + Gee.List behavior_list = behavior_map.get(table_name); + if (behavior_list != null) + foreach (FSpotBehaviorEntry entry in behavior_list) { + if (version.compare_to(entry.get_version()) >= 0) + behavior = entry.get_behavior(); + } + else + warning("Could not find behavior list for table %s", table_name); + return behavior; + + } + public FSpotDatabaseBehavior(Utils.VersionNumber version) throws Spit.DataImports.DataImportError { + if (version.compare_to(MIN_UNSUPPORTED_VERSION) >= 0) + throw new Spit.DataImports.DataImportError.UNSUPPORTED_VERSION("Version %s is not yet supported", version.to_string()); + + FSpotTableBehavior? photos_generic_behavior = find_behavior(FSpotPhotosTable.TABLE_NAME, version); + if (photos_generic_behavior != null) + photos_behavior = photos_generic_behavior as FSpotTableBehavior; + FSpotTableBehavior? tags_generic_behavior = find_behavior(FSpotTagsTable.TABLE_NAME, version); + if (tags_generic_behavior != null) + tags_behavior = tags_generic_behavior as FSpotTableBehavior; + FSpotTableBehavior? photo_tags_generic_behavior = find_behavior(FSpotPhotoTagsTable.TABLE_NAME, version); + if (photo_tags_generic_behavior != null) + photo_tags_behavior = photo_tags_generic_behavior as FSpotTableBehavior; + FSpotTableBehavior? photo_versions_generic_behavior = find_behavior(FSpotPhotoVersionsTable.TABLE_NAME, version); + if (photo_versions_generic_behavior != null) + photo_versions_behavior = photo_versions_generic_behavior as FSpotTableBehavior; + FSpotTableBehavior? rolls_generic_behavior = find_behavior(FSpotRollsTable.TABLE_NAME, version); + if (rolls_generic_behavior != null) + rolls_behavior = rolls_generic_behavior as FSpotTableBehavior; + + if (photos_behavior == null || tags_behavior == null || + photo_tags_behavior == null || photo_versions_behavior == null || + rolls_behavior == null + ) + throw new Spit.DataImports.DataImportError.UNSUPPORTED_VERSION("Version %s is not supported", version.to_string()); + } + + public FSpotTableBehavior get_photos_behavior() { + return photos_behavior; + } + + public FSpotTableBehavior get_tags_behavior() { + return tags_behavior; + } + + public FSpotTableBehavior get_photo_tags_behavior() { + return photo_tags_behavior; + } + + public FSpotTableBehavior get_photo_versions_behavior() { + return photo_versions_behavior; + } + + public FSpotTableBehavior get_rolls_behavior() { + return rolls_behavior; + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotDatabaseTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotDatabaseTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotDatabaseTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotDatabaseTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,54 @@ +/* Copyright 2009-2011 Yorba Foundation + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * This class represents a generic F-Spot table. + */ +public abstract class FSpotDatabaseTable : DatabaseTable { + protected unowned Sqlite.Database fspot_db; + protected FSpotTableBehavior behavior; + + public FSpotDatabaseTable(Sqlite.Database db) { + this.fspot_db = db; + } + + public void set_behavior(FSpotTableBehavior behavior) { + this.behavior = behavior; + set_table_name(behavior.get_table_name()); + } + + public FSpotTableBehavior get_behavior() { + return behavior; + } + + protected string get_joined_column_list(bool with_table = false) { + string[] columns = behavior.list_columns(); + if (with_table) + for (int i = 0; i < columns.length; i++) + columns[i] = "%s.%s".printf(table_name, columns[i]); + return string.joinv(", ", columns); + } + + protected int select_all(out Sqlite.Statement stmt) throws DatabaseError { + string column_list = get_joined_column_list(); + string sql = "SELECT %s FROM %s".printf(column_list, table_name); + + int res = fspot_db.prepare_v2(sql, -1, out stmt); + if (res != Sqlite.OK) + throw_error("Statement failed: %s".printf(sql), res); + + res = stmt.step(); + if (res != Sqlite.ROW && res != Sqlite.DONE) + throw_error("select_all %s %s".printf(table_name, column_list), res); + + return res; + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotDatabase.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotDatabase.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotDatabase.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotDatabase.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,58 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +public const int64 NULL_ID = 0; +public const int64 INVALID_ID = -1; + +/** + * Initialization method for the whole module. + */ +public void init() { + FSpotDatabaseBehavior.create_behavior_map(); +} + +/** + * An object that is able to read from the F-Spot + * database and extract the relevant objects. + */ +public class FSpotDatabase : Object { + private Sqlite.Database fspot_db; + private FSpotMetaTable meta_table; + public FSpotPhotosTable photos_table; + public FSpotPhotoVersionsTable photo_versions_table; + public FSpotTagsTable tags_table; + public FSpotRollsTable rolls_table; + public int64 hidden_tag_id; + + public FSpotDatabase(File db_file) throws DatabaseError, Spit.DataImports.DataImportError { + string filename = db_file.get_path(); + int res = Sqlite.Database.open_v2(filename, out fspot_db, + Sqlite.OPEN_READONLY, null); + if (res != Sqlite.OK) + throw new DatabaseError.ERROR("Unable to open F-Spot database %s: %d", filename, res); + meta_table = new FSpotMetaTable(fspot_db); + hidden_tag_id = meta_table.get_hidden_tag_id(); + + FSpotDatabaseBehavior db_behavior = new FSpotDatabaseBehavior(get_version()); + + photos_table = new FSpotPhotosTable(fspot_db, db_behavior); + photo_versions_table = new FSpotPhotoVersionsTable(fspot_db, db_behavior); + tags_table = new FSpotTagsTable(fspot_db, db_behavior); + rolls_table = new FSpotRollsTable(fspot_db, db_behavior); + } + + ~FSpotDatabase() { + } + + private Utils.VersionNumber get_version() throws DatabaseError { + return new Utils.VersionNumber.from_string(meta_table.get_db_version()); + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotImporter.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotImporter.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotImporter.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotImporter.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,567 @@ +/* Copyright 2009-2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +public class FSpotService : Object, Spit.Pluggable, Spit.DataImports.Service { + private const string ICON_FILENAME = "f-spot-24.png"; + + private static Gdk.Pixbuf[] icon_pixbuf_set = null; + + public FSpotService(GLib.File resource_directory) { + // initialize the database layer + DataImports.FSpot.Db.init(); + if (icon_pixbuf_set == null) + icon_pixbuf_set = Resources.load_icon_set(resource_directory.get_child(ICON_FILENAME)); + } + + public int get_pluggable_interface(int min_host_interface, int max_host_interface) { + return Spit.negotiate_interfaces(min_host_interface, max_host_interface, + Spit.DataImports.CURRENT_INTERFACE); + } + + public unowned string get_id() { + return "org.yorba.shotwell.dataimports.fspot"; + } + + public unowned string get_pluggable_name() { + return "F-Spot"; + } + + public void get_info(ref Spit.PluggableInfo info) { + info.authors = "Bruno Girin"; + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); + info.translators = Resources.TRANSLATORS; + info.version = _VERSION; + info.website_name = Resources.WEBSITE_NAME; + info.website_url = Resources.WEBSITE_URL; + info.is_license_wordwrapped = false; + info.license = Resources.LICENSE; + info.icons = icon_pixbuf_set; + } + + public void activation(bool enabled) { + } + + public Spit.DataImports.DataImporter create_data_importer(Spit.DataImports.PluginHost host) { + return new DataImports.FSpot.FSpotDataImporter(this, host); + } +} + +namespace DataImports.FSpot { + +internal const string SERVICE_NAME = "F-Spot"; +internal const string SERVICE_WELCOME_MESSAGE = + _("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."); +internal const string SERVICE_WELCOME_MESSAGE_FILE_ONLY = + _("Welcome to the F-Spot library import service.\n\nPlease select an F-Spot database file."); +internal const string FILE_IMPORT_LABEL = + _("Manually select an F-Spot database file to import:"); +internal const string ERROR_CANT_OPEN_DB_FILE = + _("Cannot open the selected F-Spot database file: the file does not exist or is not an F-Spot database"); +internal const string ERROR_UNSUPPORTED_DB_VERSION = + _("Cannot open the selected F-Spot database file: this version of the F-Spot database is not supported by Shotwell"); +internal const string ERROR_CANT_READ_TAGS_TABLE = + _("Cannot read the selected F-Spot database file: error while reading tags table"); +internal const string ERROR_CANT_READ_PHOTOS_TABLE = + _("Cannot read the selected F-Spot database file: error while reading photos table"); +internal const string MESSAGE_FINAL_SCREEN = + _("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."); + +public class FSpotImportableLibrary : Spit.DataImports.ImportableLibrary, GLib.Object { + private File db_file; + + public FSpotImportableLibrary(File db_file) { + this.db_file = db_file; + } + + public File get_db_file() { + return db_file; + } + + public string get_display_name() { + return _("F-Spot library: %s").printf(db_file.get_path()); + } +} + +public class FSpotImportableItem : Spit.DataImports.ImportableMediaItem, GLib.Object { + private DataImports.FSpot.Db.FSpotPhotoRow photo_row; + private DataImports.FSpot.Db.FSpotPhotoVersionRow? photo_version_row; + private DataImports.FSpot.Db.FSpotRollRow? roll_row; + private FSpotImportableTag[] tags; + private FSpotImportableEvent? event; + private FSpotImportableRating rating; + private string folder_path; + private string filename; + + public FSpotImportableItem( + DataImports.FSpot.Db.FSpotPhotoRow photo_row, + DataImports.FSpot.Db.FSpotPhotoVersionRow? photo_version_row, + DataImports.FSpot.Db.FSpotRollRow? roll_row, + FSpotImportableTag[] tags, + FSpotImportableEvent? event, + bool is_hidden, + bool is_favorite + ) { + this.photo_row = photo_row; + this.photo_version_row = photo_version_row; + this.roll_row = roll_row; + this.tags = tags; + this.event = event; + if (photo_row.rating > 0) + this.rating = new FSpotImportableRating(photo_row.rating); + else if (is_hidden) + this.rating = new FSpotImportableRating(FSpotImportableRating.REJECTED); + else if (is_favorite) + this.rating = new FSpotImportableRating(5); + else + this.rating = new FSpotImportableRating(FSpotImportableRating.UNRATED); + + // store path and filename + folder_path = (photo_version_row != null) ? + photo_version_row.base_path.get_path() : + photo_row.base_path.get_path(); + filename = (photo_version_row != null) ? + photo_version_row.filename : + photo_row.filename; + + // In theory, neither field should be null at that point but belts + // and braces don't hurt + if (folder_path != null && filename != null) { + // check if file exist and if not decode as URL + File photo = File.new_for_path(folder_path).get_child(filename); + + // If file not found, parse as URI and store back + if (!photo.query_exists()) { + folder_path = decode_url(folder_path); + filename = decode_url(filename); + } + } + } + + public Spit.DataImports.ImportableTag[] get_tags() { + Spit.DataImports.ImportableTag[] importable_tags = new Spit.DataImports.ImportableTag[0]; + foreach (FSpotImportableTag tag in tags) + importable_tags += tag; + return importable_tags; + } + + public Spit.DataImports.ImportableEvent? get_event() { + return event; + } + + public string get_folder_path() { + return folder_path; + } + + public string get_filename() { + return filename; + } + + public string? get_title() { + return (photo_row.description == null || photo_row.description == "") ? null : photo_row.description; + } + + public Spit.DataImports.ImportableRating get_rating() { + return rating; + } + + private string decode_url(string url) { + StringBuilder builder = new StringBuilder(); + for (int idx = 0; idx < url.length; ) { + int cidx = url.index_of_char('%', idx); + if (cidx > idx) { + builder.append(url.slice(idx, cidx)); + } + if (cidx >= 0) { + if (cidx < url.length - 2) { + char c1 = url.get(cidx + 1); + char c2 = url.get(cidx + 2); + if (c1.isxdigit() && c1.isxdigit()) { + int ccode = 0x10 * c1.xdigit_value() + c2.xdigit_value(); + builder.append_c((char)ccode); + } + idx = cidx + 3; + } else { + idx = cidx + 1; + } + } else { + builder.append(url.substring(idx)); + idx = url.length; + } + } + return builder.str; + } +} + +public class FSpotImportableTag : Spit.DataImports.ImportableTag, GLib.Object { + private DataImports.FSpot.Db.FSpotTagRow row; + private FSpotImportableTag? parent; + + public FSpotImportableTag(DataImports.FSpot.Db.FSpotTagRow row, FSpotImportableTag? parent) { + this.row = row; + this.parent = parent; + } + + public int64 get_id() { + return row.tag_id; + } + + public string get_name() { + return row.name; + } + + public Spit.DataImports.ImportableTag? get_parent() { + return parent; + } + + public FSpotImportableTag? get_fspot_parent() { + return parent; + } + + public string get_stock_icon() { + return row.stock_icon; + } + + public bool is_stock() { + return (row.stock_icon.has_prefix(DataImports.FSpot.Db.FSpotTagsTable.PREFIX_STOCK_ICON)); + } + + public FSpotImportableEvent to_event() { + return new FSpotImportableEvent(this.row); + } +} + +public class FSpotImportableEvent : Spit.DataImports.ImportableEvent, GLib.Object { + private DataImports.FSpot.Db.FSpotTagRow row; + + public FSpotImportableEvent(DataImports.FSpot.Db.FSpotTagRow row) { + this.row = row; + } + + public string get_name() { + return row.name; + } +} + +public class FSpotImportableRating : Spit.DataImports.ImportableRating, GLib.Object { + public static const int REJECTED = -1; + public static const int UNRATED = 0; + + private int rating_value; + + public FSpotImportableRating(int rating_value) { + if (rating_value < -1) + rating_value = -1; + else if (rating_value > 5) + rating_value = 5; + this.rating_value = rating_value; + } + + public bool is_rejected() { + return (rating_value == REJECTED); + } + + public bool is_unrated() { + return (rating_value == UNRATED); + } + + public int get_value() { + return rating_value; + } +} + +internal class FSpotTagsCache : Object { + private DataImports.FSpot.Db.FSpotTagsTable tags_table; + private Gee.HashMap tags_map; + + public FSpotTagsCache(DataImports.FSpot.Db.FSpotTagsTable tags_table) throws DatabaseError { + this.tags_table = tags_table; + tags_map = new Gee.HashMap (); + } + + public FSpotImportableTag get_tag(DataImports.FSpot.Db.FSpotTagRow tag_row) throws DatabaseError { + FSpotImportableTag? tag = tags_map.get(tag_row.tag_id); + if (tag != null) { + return tag; + } else { + FSpotImportableTag? parent_tag = get_tag_from_id(tag_row.category_id); + FSpotImportableTag new_tag = new FSpotImportableTag(tag_row, parent_tag); + tags_map[tag_row.tag_id] = new_tag; + return new_tag; + } + } + + private FSpotImportableTag? get_tag_from_id(int64 tag_id) throws DatabaseError { + // check whether the tag ID is valid first, otherwise return null + if (tag_id < 1) + return null; + FSpotImportableTag? tag = tags_map.get(tag_id); + if (tag != null) + return tag; + DataImports.FSpot.Db.FSpotTagRow? tag_row = tags_table.get_by_id(tag_id); + if (tag_row != null) { + FSpotImportableTag? parent_tag = get_tag_from_id(tag_row.category_id); + FSpotImportableTag new_tag = new FSpotImportableTag(tag_row, parent_tag); + tags_map[tag_id] = new_tag; + return new_tag; + } + return null; + } +} + +public class FSpotDataImporter : Spit.DataImports.DataImporter, GLib.Object { + + private weak Spit.DataImports.PluginHost host = null; + private weak Spit.DataImports.Service service = null; + private bool running = false; + + public FSpotDataImporter(Spit.DataImports.Service service, + Spit.DataImports.PluginHost host) { + debug("FSpotDataImporter instantiated."); + this.service = service; + this.host = host; + } + + private bool is_running() { + return running; + } + + public Spit.DataImports.Service get_service() { + return service; + } + + public void start() { + if (is_running()) + return; + + debug("FSpotDataImporter: starting interaction."); + + running = true; + + do_discover_importable_libraries(); + } + + public void stop() { + debug("FSpotDataImporter: stopping interaction."); + + running = false; + } + + // Actions and event implementation + + /** + * Action that discovers importable libraries based on standard locations. + */ + private void do_discover_importable_libraries() { + Spit.DataImports.ImportableLibrary[] discovered_libraries = + new Spit.DataImports.ImportableLibrary[0]; + + File[] db_files = { + // where the DB is in Ubuntu Lucid + File.new_for_path(Environment.get_user_config_dir()). + get_child("f-spot").get_child("photos.db"), + // where it seems to be in Ubuntu Jaunty + File.new_for_path(Environment.get_home_dir()).get_child(".gnome2"). + get_child("f-spot").get_child("photos.db"), + // where it should really be if it followed the XDG spec + File.new_for_path(Environment.get_user_data_dir()). + get_child("f-spot").get_child("photos.db") + }; + + foreach (File db_file in db_files) { + if (db_file.query_exists(null)) { + discovered_libraries += new FSpotImportableLibrary(db_file); + message("Discovered importable library: %s", db_file.get_path()); + } + } + + host.install_library_selection_pane( + (discovered_libraries.length > 0 ? SERVICE_WELCOME_MESSAGE : SERVICE_WELCOME_MESSAGE_FILE_ONLY), + discovered_libraries, + FILE_IMPORT_LABEL + ); + } + + public void on_library_selected(Spit.DataImports.ImportableLibrary library) { + on_file_selected(((FSpotImportableLibrary)library).get_db_file()); + } + + public void on_file_selected(File file) { + DataImports.FSpot.Db.FSpotDatabase database; + FSpotTagsCache tags_cache; + Gee.ArrayList all_photos; + double progress_delta_per_photo = 1.0; + double progress_plugin_to_host_ratio = 0.5; + double current_progress = 0.0; + try { + database = new DataImports.FSpot.Db.FSpotDatabase(file); + } catch(DatabaseError e) { + debug("FSpotDataImporter: Can't open database file: %s".printf(e.message)); + host.post_error_message(ERROR_CANT_OPEN_DB_FILE); + return; + } catch(Spit.DataImports.DataImportError e) { + debug("FSpotDataImporter: Unsupported F-Spot database version: %s".printf(e.message)); + host.post_error_message(ERROR_UNSUPPORTED_DB_VERSION); + return; + } + try { + tags_cache = new FSpotTagsCache(database.tags_table); + } catch(DatabaseError e) { + debug("FSpotDataImporter: Can't read tags table: %s".printf(e.message)); + host.post_error_message(ERROR_CANT_READ_TAGS_TABLE); + return; + } + host.install_import_progress_pane(_("Preparation to import")); + try { + all_photos = database.photos_table.get_all(); + } catch(DatabaseError e) { + debug("FSpotDataImporter: Can't read photos table: %s".printf(e.message)); + host.post_error_message(ERROR_CANT_READ_PHOTOS_TABLE); + return; + } + if (all_photos.size > 0) + progress_delta_per_photo = 1.0 / all_photos.size; + foreach (DataImports.FSpot.Db.FSpotPhotoRow photo_row in all_photos) { + bool hidden = false; + bool favorite = false; + FSpotImportableTag[] tags = new FSpotImportableTag[0]; + FSpotImportableEvent? event = null; + DataImports.FSpot.Db.FSpotRollRow? roll_row = null; + + // TODO: We do not convert F-Spot events to Shotwell events because F-Spot's events + // are essentially tags. We would need to detect if the tag is an event (use + // is_tag_event) and then assign the event to the photo ... since a photo can be + // in multiple F-Spot events, we would need to pick one, and since their tags + // are hierarchical, we would need to pick a name (probably the leaf) + try { + foreach ( + DataImports.FSpot.Db.FSpotTagRow tag_row in + database.tags_table.get_by_photo_id(photo_row.photo_id) + ) { + FSpotImportableTag tag = tags_cache.get_tag(tag_row); + if (is_tag_hidden(tag, database.hidden_tag_id)) + hidden = true; + else if (is_tag_favorite(tag)) + favorite = true; + else + tags += tag; + } + } catch(DatabaseError e) { + // log the error and leave the tag list empty + message("Failed to retrieve tags for photo ID %ld: %s", (long) photo_row.photo_id, + e.message); + } + + try { + roll_row = database.rolls_table.get_by_id(photo_row.roll_id); + } catch (DatabaseError e) { + // log the error and leave the roll row null + message("Failed to retrieve roll for photo ID %ld: %s", (long) photo_row.photo_id, + e.message); + } + + Spit.DataImports.ImportableMediaItem[] importable_items = new Spit.DataImports.ImportableMediaItem[0]; + try { + Gee.ArrayList photo_versions = + database.photo_versions_table.get_by_photo_id(photo_row.photo_id); + bool photo_versions_added = false; // set to true if at least one version was added + bool photo_versions_skipped = false; // set to true if at least one version was skipped due to missing file details + foreach (DataImports.FSpot.Db.FSpotPhotoVersionRow photo_version_row in photo_versions) { + if (photo_version_row.base_path != null && photo_version_row.filename != null) { + importable_items += new FSpotImportableItem( + photo_row, photo_version_row, roll_row, tags, event, hidden, favorite + ); + photo_versions_added = true; + } else { + photo_versions_skipped = true; + } + } + + // Older versions of F-Spot (0.4.3.1 at least, perhaps later) did not maintain photo_versions, + // this handles that case + // It also handles the case when we had to skip any photo version due to missing + // file details + if (photo_versions_skipped || !photo_versions_added) { + if (photo_row.base_path != null && photo_row.filename != null) { + importable_items += new FSpotImportableItem( + photo_row, null, roll_row, tags, event, hidden, favorite + ); + } + } + } catch (DatabaseError e) { + // if we can't load the different versions, do the best we can + // and create one photo from the photo row that was found earlier + message("Failed to retrieve versions for photo ID %ld: %s", (long) photo_row.photo_id, + e.message); + if (photo_row.base_path != null && photo_row.filename != null) { + importable_items += new FSpotImportableItem( + photo_row, null, roll_row, tags, event, hidden, favorite + ); + } + } + // If the importer is still running, import the items and loop, + // otherwise break the loop + if (running) { + host.prepare_media_items_for_import( + importable_items, + current_progress + (progress_delta_per_photo * progress_plugin_to_host_ratio), + progress_delta_per_photo * (1 - progress_plugin_to_host_ratio), + null + ); + current_progress += progress_delta_per_photo; + host.update_import_progress_pane(current_progress); + } else { + break; + } + } + host.finalize_import(on_imported_items_count); + } + + public void on_imported_items_count(int imported_items_count) { + host.install_static_message_pane( + MESSAGE_FINAL_SCREEN.printf(imported_items_count), + Spit.DataImports.PluginHost.ButtonMode.CLOSE + ); + } + + private bool is_tag_event(FSpotImportableTag tag) { + bool result = (DataImports.FSpot.Db.FSpotTagsTable.STOCK_ICON_EVENTS == tag.get_stock_icon()); + if (!result) { + FSpotImportableTag? parent = tag.get_fspot_parent(); + if (parent == null) + result = false; + else + result = is_tag_event(parent); + } + return result; + } + + private bool is_tag_hidden(FSpotImportableTag tag, int64 hidden_tag_id) { + bool result = (hidden_tag_id == tag.get_id()); + if (!result) { + FSpotImportableTag? parent = tag.get_fspot_parent(); + if (parent == null) + result = false; + else + result = is_tag_hidden(parent, hidden_tag_id); + } + return result; + } + + private bool is_tag_favorite(FSpotImportableTag tag) { + bool result = (DataImports.FSpot.Db.FSpotTagsTable.STOCK_ICON_FAV == tag.get_stock_icon()); + if (!result) { + FSpotImportableTag? parent = tag.get_fspot_parent(); + if (parent == null) + result = false; + else + result = is_tag_favorite(parent); + } + return result; + } +} + +} // namespace + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotMetaTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotMetaTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotMetaTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotMetaTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,113 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * The value object for the "meta" table, representing a single database row. + */ +public class FSpotMetaRow : Object { + // ignore the ID + public string name; + public string data; +} + +/** + * This class represents the F-Spot meta table, which stores some essential + * meta-data for the whole database. It is implemented as a simple dictionary + * where each row in the table is a key/value pair. + * + * The meta table implementation is the only one that throws a database error + * if something goes wrong because: + * * it is essential to read the content of that table in order to identify + * the version of the database and select the correct behavior, + * * this table is read at the very beginning of the process so any failure + * will occur immediately, + * * failing to read this table means that there is no point in reading the + * attempting to read the rest of the database so we might as well abort. + */ +public class FSpotMetaTable : FSpotDatabaseTable { + + public FSpotMetaTable(Sqlite.Database db) { + base(db); + set_behavior(FSpotMetaBehavior.get_instance()); + } + + public string? get_data(string name) throws DatabaseError { + string[] columns = behavior.list_columns(); + string column_list = string.joinv(", ", columns); + string sql = "SELECT %s FROM %s WHERE name=?".printf(column_list, table_name); + Sqlite.Statement stmt; + int res = fspot_db.prepare_v2(sql, -1, out stmt); + if (res != Sqlite.OK) + throw_error("Statement failed: %s".printf(sql), res); + + res = stmt.bind_text(1, name); + if (res != Sqlite.OK) + throw_error("Bind failed for name %s".printf(name), res); + + res = stmt.step(); + if (res != Sqlite.ROW) { + if (res != Sqlite.DONE) + throw_error("FSpotMetaTable.get_data", res); + + return null; + } + + FSpotMetaRow row; + behavior.build_row(stmt, out row); + return row.data; + } + + public string? get_app_version() throws DatabaseError { + return get_data("F-Spot Version"); + } + + public string? get_db_version() throws DatabaseError { + return get_data("F-Spot Database Version"); + } + + public int64 get_hidden_tag_id() throws DatabaseError { + string id_str = get_data("Hidden Tag Id"); + if(id_str != null) { + return int64.parse(id_str); + } else { + return -1; + } + } +} + +public class FSpotMetaBehavior : FSpotTableBehavior, Object { + public static const string TABLE_NAME = "Meta"; + + private static FSpotMetaBehavior instance; + + private FSpotMetaBehavior() { + } + + public static FSpotMetaBehavior get_instance() { + if (instance == null) + instance = new FSpotMetaBehavior(); + return instance; + } + + public string get_table_name() { + return TABLE_NAME; + } + + public string[] list_columns() { + return { "name", "data" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotMetaRow row, int offset = 0) { + row = new FSpotMetaRow(); + row.name = stmt.column_text(offset + 0); + row.data = stmt.column_text(offset + 1); + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotPhotosTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotPhotosTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotPhotosTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotPhotosTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,356 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * The value object for the "photos" table, representing a single database row. + */ +public class FSpotPhotoRow : Object { + public int64 photo_id; + public time_t time; + public File? base_path; + public string? filename; + public string description; + public int64 roll_id; + public int64 default_version_id; + public int rating; + public string md5_sum; +} + +/** + * This class represents the F-Spot photos table. + */ +public class FSpotPhotosTable : FSpotDatabaseTable { + public static const string TABLE_NAME = "Photos"; + + public FSpotPhotosTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { + base(db); + set_behavior(db_behavior.get_photos_behavior()); + } + + public Gee.ArrayList get_all() throws DatabaseError { + Gee.ArrayList all = new Gee.ArrayList(); + + Sqlite.Statement stmt; + int res = select_all(out stmt); + while (res == Sqlite.ROW) { + FSpotPhotoRow row; + behavior.build_row(stmt, out row); + all.add(row); + res = stmt.step(); + } + + return all; + } +} + +// Photos table behavior for v0-4 +// The original table format +public class FSpotPhotosV0Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV0Behavior instance; + + private FSpotPhotosV0Behavior() { + } + + public static FSpotPhotosV0Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV0Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "directory_path", "name", "description", + "default_version_id" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? base_path = stmt.column_text(offset + 2); + string? filename = stmt.column_text(offset + 3); + if (base_path != null && filename != null) { + row.base_path = File.new_for_uri(base_path); + row.filename = filename; + } + + row.description = stmt.column_text(offset + 4); + row.roll_id = INVALID_ID; + row.default_version_id = stmt.column_int64(offset + 5); + row.rating = 0; + row.md5_sum = ""; + } +} + +// Photos table behavior for v5-6 +// v5 introduced a roll_id to reference the imported roll (rolls were a new +// table migrated from imports) +public class FSpotPhotosV5Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV5Behavior instance; + + private FSpotPhotosV5Behavior() { + } + + public static FSpotPhotosV5Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV5Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "directory_path", "name", "description", "roll_id", + "default_version_id" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? base_path = stmt.column_text(offset + 2); + string? filename = stmt.column_text(offset + 3); + if (base_path != null && filename != null) { + row.base_path = File.new_for_uri(base_path); + row.filename = filename; + } + + row.description = stmt.column_text(offset + 4); + row.roll_id = stmt.column_int64(offset + 5); + row.default_version_id = stmt.column_int64(offset + 6); + row.rating = 0; + row.md5_sum = ""; + } +} + +// Photos table behavior for v7-10 +// v7 merged directory_path and name into a single URI value with a file:// +// prefix; presumaly this is meant to be able to handle remote files using a +// different URI prefix such as remote files +public class FSpotPhotosV7Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV7Behavior instance; + + private FSpotPhotosV7Behavior() { + } + + public static FSpotPhotosV7Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV7Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "uri", "description", "roll_id", + "default_version_id" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? full_path = stmt.column_text(offset + 2); + if (full_path != null) { + File uri = File.new_for_uri(full_path); + row.base_path = uri.get_parent(); + row.filename = uri.get_basename(); + } + + row.description = stmt.column_text(offset + 3); + row.roll_id = stmt.column_int64(offset + 4); + row.default_version_id = stmt.column_int64(offset + 5); + row.rating = 0; + row.md5_sum = ""; + } +} + +// Photos table behavior for v11-15 +// v11 introduced the concept of rating so add this to the list of fields +public class FSpotPhotosV11Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV11Behavior instance; + + private FSpotPhotosV11Behavior() { + } + + public static FSpotPhotosV11Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV11Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "uri", "description", "roll_id", + "default_version_id", "rating" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? full_path = stmt.column_text(offset + 2); + if (full_path != null) { + File uri = File.new_for_uri(full_path); + row.base_path = uri.get_parent(); + row.filename = uri.get_basename(); + } + + row.description = stmt.column_text(offset + 3); + row.roll_id = stmt.column_int64(offset + 4); + row.default_version_id = stmt.column_int64(offset + 5); + row.rating = stmt.column_int(offset + 6); + row.md5_sum = ""; + } +} + +// Photos table behavior for v16 +// v16 introduced the MD5 sum so add this to the list of fields +public class FSpotPhotosV16Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV16Behavior instance; + + private FSpotPhotosV16Behavior() { + } + + public static FSpotPhotosV16Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV16Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "uri", "description", "roll_id", + "default_version_id", "rating", "md5_sum" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? full_path = stmt.column_text(offset + 2); + if (full_path != null) { + File uri = File.new_for_uri(full_path); + row.base_path = uri.get_parent(); + row.filename = uri.get_basename(); + } + + row.description = stmt.column_text(offset + 3); + row.roll_id = stmt.column_int64(offset + 4); + row.default_version_id = stmt.column_int64(offset + 5); + row.rating = stmt.column_int(offset + 6); + row.md5_sum = stmt.column_text(offset + 7); + } +} + +// Photos table behavior for v17 +// v17 split the URI into base_uri and filename (reverting back to the original +// design introduced in v0, albeit with a URI rather than a file system path) +public class FSpotPhotosV17Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV17Behavior instance; + + private FSpotPhotosV17Behavior() { + } + + public static FSpotPhotosV17Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV17Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "base_uri", "filename", "description", "roll_id", + "default_version_id", "rating", "md5_sum" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? base_path = stmt.column_text(offset + 2); + string? filename = stmt.column_text(offset + 3); + if (base_path != null && filename != null) { + row.base_path = File.new_for_uri(base_path); + row.filename = filename; + } + + row.description = stmt.column_text(offset + 4); + row.roll_id = stmt.column_int64(offset + 5); + row.default_version_id = stmt.column_int64(offset + 6); + row.rating = stmt.column_int(offset + 7); + row.md5_sum = stmt.column_text(offset + 8); + } +} + +// v18: no more MD5 hash in the photos table: moved to photo_versions table +public class FSpotPhotosV18Behavior : FSpotTableBehavior, Object { + private static FSpotPhotosV18Behavior instance; + + private FSpotPhotosV18Behavior() { + } + + public static FSpotPhotosV18Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotosV18Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotosTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time", "base_uri", "filename", "description", "roll_id", + "default_version_id", "rating" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { + row = new FSpotPhotoRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + + string? base_path = stmt.column_text(offset + 2); + string? filename = stmt.column_text(offset + 3); + if (base_path != null && filename != null) { + row.base_path = File.new_for_uri(base_path); + row.filename = filename; + } + + row.description = stmt.column_text(offset + 4); + row.roll_id = stmt.column_int64(offset + 5); + row.default_version_id = stmt.column_int64(offset + 6); + row.rating = stmt.column_int(offset + 7); + row.md5_sum = ""; + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,57 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * The value object for the "photo_tags" table, representing a single database row. + */ +public class FSpotPhotoTagRow : Object { + public int64 photo_id; + public int64 tag_id; +} + +/** + * This class represents the F-Spot photo_tags table. + */ +public class FSpotPhotoTagsTable : FSpotDatabaseTable { + public static const string TABLE_NAME = "Photo_Tags"; + + public FSpotPhotoTagsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { + base(db); + set_behavior(db_behavior.get_photo_tags_behavior()); + } +} + +public class FSpotPhotoTagsV0Behavior : FSpotTableBehavior, Object { + private static FSpotPhotoTagsV0Behavior instance; + + private FSpotPhotoTagsV0Behavior() { + } + + public static FSpotPhotoTagsV0Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotoTagsV0Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotoTagsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "photo_id", "tag_id" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoTagRow row, int offset = 0) { + row = new FSpotPhotoTagRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.tag_id = stmt.column_int64(offset + 1); + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,271 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * The value object for the "photo_versions" table, representing a single database row. + */ +public class FSpotPhotoVersionRow : Object { + public int64 photo_id; + public int64 version_id; + public string name; + public File? base_path; + public string? filename; + public string md5_sum; + public bool is_protected; +} + +/** + * This class represents the F-Spot photo_versions table. + */ +public class FSpotPhotoVersionsTable : FSpotDatabaseTable { + public static const string TABLE_NAME = "Photo_versions"; + + public FSpotPhotoVersionsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { + base(db); + set_behavior(db_behavior.get_photo_versions_behavior()); + } + + public Gee.ArrayList get_by_photo_id(int64 photo_id) throws DatabaseError { + Gee.ArrayList rows = new Gee.ArrayList(); + + Sqlite.Statement stmt; + + string column_list = get_joined_column_list(); + string sql = "SELECT %s FROM %s WHERE photo_id=?".printf( + column_list, table_name + ); + + int res = fspot_db.prepare_v2(sql, -1, out stmt); + if (res != Sqlite.OK) + throw_error("Statement failed: %s".printf(sql), res); + + res = stmt.bind_int64(1, photo_id); + if (res != Sqlite.OK) + throw_error("Bind failed for photo_id", res); + + res = stmt.step(); + while (res == Sqlite.ROW) { + FSpotPhotoVersionRow row; + behavior.build_row(stmt, out row); + rows.add(row); + res = stmt.step(); + } + + return rows; + } +} + +// Photo_versions table behavior for v0-8 +// Note: there is a change in the URI format in version 8 but the File.new_for_uri +// constructor should be able to deal with the variation, so the v8 behavior should +// be handled in a way identical to v0-7 +public class FSpotPhotoVersionsV0Behavior : FSpotTableBehavior, Object { + private static FSpotPhotoVersionsV0Behavior instance; + + private FSpotPhotoVersionsV0Behavior() { + } + + public static FSpotPhotoVersionsV0Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotoVersionsV0Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotoVersionsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "photo_id", "version_id", "name", "uri" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { + row = new FSpotPhotoVersionRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.version_id = stmt.column_int64(offset + 1); + row.name = stmt.column_text(offset + 2); + + string? full_path = stmt.column_text(offset + 3); + if (full_path != null) { + File uri = File.new_for_uri(full_path); + row.base_path = uri.get_parent(); + row.filename = uri.get_basename(); + } + + row.md5_sum = ""; + row.is_protected = false; + } +} + +// Photo_versions table behavior for v9-15 +// add protected field +public class FSpotPhotoVersionsV9Behavior : FSpotTableBehavior, Object { + private static FSpotPhotoVersionsV9Behavior instance; + + private FSpotPhotoVersionsV9Behavior() { + } + + public static FSpotPhotoVersionsV9Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotoVersionsV9Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotoVersionsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "photo_id", "version_id", "name", "uri", + "protected" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { + row = new FSpotPhotoVersionRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.version_id = stmt.column_int64(offset + 1); + row.name = stmt.column_text(offset + 2); + + string? full_path = stmt.column_text(offset + 3); + if (full_path != null) { + File uri = File.new_for_uri(full_path); + row.base_path = uri.get_parent(); + row.filename = uri.get_basename(); + } + + row.md5_sum = ""; + row.is_protected = (stmt.column_int(offset + 4) > 0); + } +} + +// Photo_versions table behavior for v16 +// add md5_sum in photo_versions +public class FSpotPhotoVersionsV16Behavior : FSpotTableBehavior, Object { + private static FSpotPhotoVersionsV16Behavior instance; + + private FSpotPhotoVersionsV16Behavior() { + } + + public static FSpotPhotoVersionsV16Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotoVersionsV16Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotoVersionsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "photo_id", "version_id", "name", "uri", + "md5_sum", "protected" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { + row = new FSpotPhotoVersionRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.version_id = stmt.column_int64(offset + 1); + row.name = stmt.column_text(offset + 2); + + string? full_path = stmt.column_text(offset + 3); + if (full_path != null) { + File uri = File.new_for_uri(full_path); + row.base_path = uri.get_parent(); + row.filename = uri.get_basename(); + } + + row.md5_sum = stmt.column_text(offset + 4); + row.is_protected = (stmt.column_int(offset + 5) > 0); + } +} + +// Photo_versions table behavior for v17 +// v17 split the URI into base_uri and filename (reverting back to the original +// design introduced in v0, albeit with a URI rather than a file system path) +public class FSpotPhotoVersionsV17Behavior : FSpotTableBehavior, Object { + private static FSpotPhotoVersionsV17Behavior instance; + + private FSpotPhotoVersionsV17Behavior() { + } + + public static FSpotPhotoVersionsV17Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotoVersionsV17Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotoVersionsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "photo_id", "version_id", "name", "base_uri", "filename", + "md5_sum", "protected" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { + row = new FSpotPhotoVersionRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.version_id = stmt.column_int64(offset + 1); + row.name = stmt.column_text(offset + 2); + + string? base_path = stmt.column_text(offset + 3); + string? filename = stmt.column_text(offset + 4); + if (base_path != null && filename != null) { + row.base_path = File.new_for_uri(base_path); + row.filename = filename; + } + + row.md5_sum = stmt.column_text(offset + 5); + row.is_protected = (stmt.column_int(offset + 6) > 0); + } +} + +// Photo_versions table behavior for v18 +// md5_sum renamed import_md5 +public class FSpotPhotoVersionsV18Behavior : FSpotTableBehavior, Object { + private static FSpotPhotoVersionsV18Behavior instance; + + private FSpotPhotoVersionsV18Behavior() { + } + + public static FSpotPhotoVersionsV18Behavior get_instance() { + if (instance == null) + instance = new FSpotPhotoVersionsV18Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotPhotoVersionsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "photo_id", "version_id", "name", "base_uri", "filename", + "import_md5", "protected" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { + row = new FSpotPhotoVersionRow(); + row.photo_id = stmt.column_int64(offset + 0); + row.version_id = stmt.column_int64(offset + 1); + row.name = stmt.column_text(offset + 2); + + string? base_path = stmt.column_text(offset + 3); + string? filename = stmt.column_text(offset + 4); + if (base_path != null && filename != null) { + row.base_path = File.new_for_uri(base_path); + row.filename = filename; + } + + row.md5_sum = stmt.column_text(offset + 5); + row.is_protected = (stmt.column_int(offset + 6) > 0); + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotRollsTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotRollsTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotRollsTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotRollsTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,111 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * The value object for the "rolls" table, representing a single database row. + */ +public class FSpotRollRow : Object { + public int64 id; + public time_t time; +} + +/** + * This class represents the F-Spot rolls table. + */ +public class FSpotRollsTable : FSpotDatabaseTable { + public static const string TABLE_NAME = "Rolls"; + public static const string TABLE_NAME_PRE_V5 = "Imports"; + + public FSpotRollsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { + base(db); + set_behavior(db_behavior.get_rolls_behavior()); + } + + public FSpotRollRow? get_by_id(int64 roll_id) throws DatabaseError { + Sqlite.Statement stmt; + FSpotRollRow? row = null; + string column_list = get_joined_column_list(); + string sql = "SELECT %s FROM %s WHERE id=?".printf(column_list, table_name); + + int res = fspot_db.prepare_v2(sql, -1, out stmt); + if (res != Sqlite.OK) + throw_error("Statement failed: %s".printf(sql), res); + + res = stmt.bind_int64(1, roll_id); + if (res != Sqlite.OK) + throw_error("Bind failed for roll_id", res); + + res = stmt.step(); + if (res == Sqlite.ROW) + behavior.build_row(stmt, out row); + else if (res == Sqlite.DONE) + message("Could not find roll row with ID %d", (int)roll_id); + + return row; + } +} + +// Rolls table behavior for v0-4 +public class FSpotRollsV0Behavior : FSpotTableBehavior, Object { + private static FSpotRollsV0Behavior instance; + + private FSpotRollsV0Behavior() { + } + + public static FSpotRollsV0Behavior get_instance() { + if (instance == null) + instance = new FSpotRollsV0Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotRollsTable.TABLE_NAME_PRE_V5; + } + + public string[] list_columns() { + return { "id", "time" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotRollRow row, int offset = 0) { + row = new FSpotRollRow(); + row.id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + } +} + +// Rolls table behavior for v5+ +// Table name changed from "imports" to "rolls" +public class FSpotRollsV5Behavior : FSpotTableBehavior, Object { + private static FSpotRollsV5Behavior instance; + + private FSpotRollsV5Behavior() { + } + + public static FSpotRollsV5Behavior get_instance() { + if (instance == null) + instance = new FSpotRollsV5Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotRollsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "time" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotRollRow row, int offset = 0) { + row = new FSpotRollRow(); + row.id = stmt.column_int64(offset + 0); + row.time = (time_t) stmt.column_int64(offset + 1); + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotTableBehavior.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotTableBehavior.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotTableBehavior.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotTableBehavior.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,28 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * This class defines a generic table behavior. In practice, it implements + * the concept of a DAO (Data Access Object) in ORM terms and is responsible + * for transforming the data extracted from a relational statement into a + * lightweight value object. + * + * The type T defined in the generic is the value object type a behavior + * implementation is designed to handle. Value object types are designed to + * contain the data for a single database row. + */ +public interface FSpotTableBehavior : Object { + public abstract string get_table_name(); + + public abstract string[] list_columns(); + + public abstract void build_row(Sqlite.Statement stmt, out T row, int offset = 0); +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/FSpotTagsTable.vala shotwell-0.11.92/plugins/shotwell-data-imports/FSpotTagsTable.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/FSpotTagsTable.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/FSpotTagsTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,129 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImports.FSpot.Db { + +/** + * The value object for the "tags" table, representing a single database row. + */ +public class FSpotTagRow : Object { + public int64 tag_id; + public string name; + public int64 category_id; + public bool is_category; + public int sort_priority; + public string stock_icon; // only store stock icons +} + +/** + * This class represents the F-Spot tags table. + */ +public class FSpotTagsTable : FSpotDatabaseTable { + public static const string TABLE_NAME = "Tags"; + + public static const string PREFIX_STOCK_ICON = "stock_icon:"; + public static const string STOCK_ICON_FAV = "stock_icon:emblem-favorite"; + public static const string STOCK_ICON_PEOPLE = "stock_icon:emblem-people"; + public static const string STOCK_ICON_PLACES = "stock_icon:emblem-places"; + public static const string STOCK_ICON_EVENTS = "stock_icon:emblem-event"; + + private FSpotTableBehavior photo_tags_behavior; + + public FSpotTagsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { + base(db); + set_behavior(db_behavior.get_tags_behavior()); + photo_tags_behavior = db_behavior.get_photo_tags_behavior(); + } + + public FSpotTagRow? get_by_id(int64 tag_id) throws DatabaseError { + Sqlite.Statement stmt; + FSpotTagRow? row = null; + string column_list = get_joined_column_list(); + string sql = "SELECT %s FROM %s WHERE id=?".printf(column_list, table_name); + + int res = fspot_db.prepare_v2(sql, -1, out stmt); + if (res != Sqlite.OK) + throw_error("Statement failed: %s".printf(sql), res); + + res = stmt.bind_int64(1, tag_id); + assert(res == Sqlite.OK); + + res = stmt.step(); + if (res == Sqlite.ROW) + behavior.build_row(stmt, out row); + else if (res == Sqlite.DONE) + message("Could not find tag row with ID %d", (int)tag_id); + + return row; + } + + public Gee.ArrayList get_by_photo_id(int64 photo_id) throws DatabaseError { + Gee.ArrayList rows = new Gee.ArrayList(); + + Sqlite.Statement stmt; + + string column_list = get_joined_column_list(true); + string sql = "SELECT %1$s FROM %2$s, %3$s WHERE %3$s.photo_id=? AND %3$s.tag_id = %2$s.id".printf( + column_list, table_name, photo_tags_behavior.get_table_name() + ); + + int res = fspot_db.prepare_v2(sql, -1, out stmt); + if (res != Sqlite.OK) + throw_error("Statement failed: %s".printf(sql), res); + + res = stmt.bind_int64(1, photo_id); + if (res != Sqlite.OK) + throw_error("Bind failed for photo_id", res); + + res = stmt.step(); + while (res == Sqlite.ROW) { + FSpotTagRow row; + behavior.build_row(stmt, out row); + rows.add(row); + res = stmt.step(); + } + + return rows; + } +} + +public class FSpotTagsV0Behavior : FSpotTableBehavior, Object { + private static FSpotTagsV0Behavior instance; + + private FSpotTagsV0Behavior() { + } + + public static FSpotTagsV0Behavior get_instance() { + if (instance == null) + instance = new FSpotTagsV0Behavior(); + return instance; + } + + public string get_table_name() { + return FSpotTagsTable.TABLE_NAME; + } + + public string[] list_columns() { + return { "id", "name", "category_id", "is_category", "sort_priority", "icon" }; + } + + public void build_row(Sqlite.Statement stmt, out FSpotTagRow row, int offset = 0) { + row = new FSpotTagRow(); + row.tag_id = stmt.column_int64(offset + 0); + row.name = stmt.column_text(offset + 1); + row.category_id = stmt.column_int64(offset + 2); + row.is_category = (stmt.column_int(offset + 3) > 0); + row.sort_priority = stmt.column_int(offset + 4); + string icon_str = stmt.column_text(offset + 5); + if (icon_str != null && icon_str.has_prefix(FSpotTagsTable.PREFIX_STOCK_ICON)) + row.stock_icon = icon_str; + else + row.stock_icon = ""; + } +} + +} + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/Makefile shotwell-0.11.92/plugins/shotwell-data-imports/Makefile --- shotwell-0.11.91/plugins/shotwell-data-imports/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/Makefile 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,30 @@ + +PLUGIN := shotwell-data-imports + +PLUGIN_PKGS := \ + gtk+-3.0 \ + gexiv2 \ + gee-1.0 \ + sqlite3 + +SRC_FILES := \ + shotwell-data-imports.vala \ + ../common/VersionNumber.vala \ + ../common/SqliteSupport.vala \ + FSpotImporter.vala \ + FSpotDatabaseBehavior.vala \ + FSpotDatabase.vala \ + FSpotDatabaseTable.vala \ + FSpotTableBehavior.vala \ + FSpotMetaTable.vala \ + FSpotPhotosTable.vala \ + FSpotPhotoTagsTable.vala \ + FSpotPhotoVersionsTable.vala \ + FSpotRollsTable.vala \ + FSpotTagsTable.vala + +RC_FILES := \ + f-spot-24.png + +include ../Makefile.plugin.mk + diff -Nru shotwell-0.11.91/plugins/shotwell-data-imports/shotwell-data-imports.vala shotwell-0.11.92/plugins/shotwell-data-imports/shotwell-data-imports.vala --- shotwell-0.11.91/plugins/shotwell-data-imports/shotwell-data-imports.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-data-imports/shotwell-data-imports.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,46 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +extern const string _VERSION; + +// "core services" are: F-Spot +private class ShotwellDataImportsCoreServices : Object, Spit.Module { + private Spit.Pluggable[] pluggables = new Spit.Pluggable[0]; + + // we need to get a module file handle because our pluggables have to load resources from the + // module file directory + public ShotwellDataImportsCoreServices(GLib.File module_file) { + GLib.File resource_directory = module_file.get_parent(); + + pluggables += new FSpotService(resource_directory); + } + + public unowned string get_module_name() { + return _("Core Data Import Services"); + } + + public unowned string get_version() { + return _VERSION; + } + + public unowned string get_id() { + return "org.yorba.shotwell.data_imports.core_services"; + } + + public unowned Spit.Pluggable[]? get_pluggables() { + return pluggables; + } +} + +// This entry point is required for all SPIT modules. +public Spit.Module? spit_entry_point(Spit.EntryPointParams *params) { + params->module_spit_interface = Spit.negotiate_interfaces(params->host_min_spit_interface, + params->host_max_spit_interface, Spit.CURRENT_INTERFACE); + + return (params->module_spit_interface != Spit.UNSUPPORTED_INTERFACE) + ? new ShotwellDataImportsCoreServices(params->module_file) : null; +} + diff -Nru shotwell-0.11.91/plugins/shotwell-publishing/FacebookPublishing.vala shotwell-0.11.92/plugins/shotwell-publishing/FacebookPublishing.vala --- shotwell-0.11.91/plugins/shotwell-publishing/FacebookPublishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing/FacebookPublishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -29,7 +29,7 @@ public void get_info(ref Spit.PluggableInfo info) { info.authors = "Lucas Beeler"; - info.copyright = _("Copyright 2009-2011 Yorba Foundation"); + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); info.translators = Resources.TRANSLATORS; info.version = _VERSION; info.website_name = Resources.WEBSITE_NAME; diff -Nru shotwell-0.11.91/plugins/shotwell-publishing/FlickrPublishing.vala shotwell-0.11.92/plugins/shotwell-publishing/FlickrPublishing.vala --- shotwell-0.11.91/plugins/shotwell-publishing/FlickrPublishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing/FlickrPublishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -29,7 +29,7 @@ public void get_info(ref Spit.PluggableInfo info) { info.authors = "Lucas Beeler"; - info.copyright = _("Copyright 2009-2011 Yorba Foundation"); + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); info.translators = Resources.TRANSLATORS; info.version = _VERSION; info.website_name = Resources.WEBSITE_NAME; @@ -56,7 +56,7 @@ internal const string SERVICE_NAME = "Flickr"; internal const string SERVICE_WELCOME_MESSAGE = - _("You are not currently logged into Flickr.\n\nYou must have already signed up for a Flickr account to complete the login process. During login you will have to specifically authorize Shotwell Connect to link to your Flickr account."); + _("You are not currently logged into Flickr.\n\nClick Login to log into Flickr in your Web browser. You will have to authorize Shotwell Connect to link to your Flickr account."); internal const string RESTART_ERROR_MESSAGE = _("You have already logged in and out of Flickr during this Shotwell session.\nTo continue publishing to Flickr, quit and restart Shotwell, then try publishing again."); internal const string ENDPOINT_URL = "http://api.flickr.com/services/rest"; @@ -64,6 +64,7 @@ internal const string API_SECRET = "d0960565e03547c1"; internal const int ORIGINAL_SIZE = -1; internal const string EXPIRED_SESSION_ERROR_CODE = "98"; +internal const string ENCODE_RFC_3986_EXTRA = "!*'();:@&=+$,/?%#[] \\"; internal enum UserKind { PRO, @@ -100,9 +101,9 @@ private Spit.Publishing.ProgressCallback progress_reporter = null; private bool running = false; private bool was_started = false; - private Session session; - private string? frob = null; - private WebAuthenticationPane web_auth_pane = null; + private Session session = null; + private PublishingOptionsPane publishing_options_pane = null; + private PublishingParameters parameters = null; public FlickrPublisher(Spit.Publishing.Service service, @@ -112,31 +113,48 @@ this.host = host; this.session = new Session(); this.parameters = new PublishingParameters(); + + session.authenticated.connect(on_session_authenticated); + } + + ~FlickrPublisher() { + session.authenticated.disconnect(on_session_authenticated); } private void invalidate_persistent_session() { - host.unset_config_key("auth_token"); - host.unset_config_key("username"); + set_persistent_access_phase_token(""); + set_persistent_access_phase_token_secret(""); + set_persistent_access_phase_username(""); } private bool is_persistent_session_valid() { - return (get_persistent_username() != null && get_persistent_auth_token() != null); + return (get_persistent_access_phase_username() != null && + get_persistent_access_phase_token() != null && + get_persistent_access_phase_token_secret() != null); } - private string? get_persistent_username() { - return host.get_config_string("username", null); + private string? get_persistent_access_phase_username() { + return host.get_config_string("access_phase_username", null); } - private void set_persistent_username(string username) { - host.set_config_string("username", username); + private void set_persistent_access_phase_username(string username) { + host.set_config_string("access_phase_username", username); } - - private string? get_persistent_auth_token() { - return host.get_config_string("auth_token", null); + + private string? get_persistent_access_phase_token() { + return host.get_config_string("access_phase_token", null); } - private void set_persistent_auth_token(string auth_token) { - host.set_config_string("auth_token", auth_token); + private void set_persistent_access_phase_token(string token) { + host.set_config_string("access_phase_token", token); + } + + private string? get_persistent_access_phase_token_secret() { + return host.get_config_string("access_phase_token_secret", null); + } + + private void set_persistent_access_phase_token_secret(string secret) { + host.set_config_string("access_phase_token_secret", secret); } private void on_welcome_pane_login_clicked() { @@ -145,109 +163,100 @@ debug("EVENT: user clicked 'Login' button in the welcome pane"); - do_obtain_frob(); + do_run_authentication_request_transaction(); } - private void on_frob_fetch_txn_completed(Publishing.RESTSupport.Transaction txn) { - txn.completed.disconnect(on_frob_fetch_txn_completed); - txn.network_error.disconnect(on_frob_fetch_txn_error); + private void on_auth_request_txn_completed(Publishing.RESTSupport.Transaction txn) { + txn.completed.disconnect(on_auth_request_txn_completed); + txn.network_error.disconnect(on_auth_request_txn_error); if (!is_running()) return; - debug("EVENT: finished network transaction to get Yahoo! login frob. "); - do_extract_frob_from_xml(txn.get_response()); + debug("EVENT: OAuth authentication request transaction completed; response = '%s'", + txn.get_response()); + + do_parse_token_info_from_auth_request(txn.get_response()); } - private void on_frob_fetch_txn_error(Publishing.RESTSupport.Transaction txn, + private void on_auth_request_txn_error(Publishing.RESTSupport.Transaction txn, Spit.Publishing.PublishingError err) { - txn.completed.disconnect(on_frob_fetch_txn_completed); - txn.network_error.disconnect(on_frob_fetch_txn_error); + txn.completed.disconnect(on_auth_request_txn_completed); + txn.network_error.disconnect(on_auth_request_txn_error); if (!is_running()) return; - debug("EVENT: network transaction to obtain Yahoo! login frob failed; response = '%s'", - txn.get_response()); - + debug("EVENT: OAuth authentication request transaction caused a network error"); host.post_error(err); } + + private void on_authentication_token_available(string token, string token_secret) { + debug("EVENT: OAuth authentication token (%s) and token secret (%s) available", + token, token_secret); - private void on_login_url_available(string login_url) { - if (!is_running()) - return; + session.set_request_phase_credentials(token, token_secret); - debug("EVENT: hosted web login url = '%s' has become available", login_url); - do_start_hosted_web_authentication(login_url); + do_launch_system_browser(token); } - - private void on_frob_available(string frob) { + + private void on_system_browser_launched() { if (!is_running()) return; - debug("EVENT: Yahoo! login frob = '%s' has become available", frob); - do_build_login_url_from_frob(frob); + debug("EVENT: system browser launched."); + + do_show_pin_entry_pane(); } - - private void on_web_auth_pane_token_check_required() { + + private void on_pin_entry_proceed(PinEntryPane sender, string pin) { + sender.proceed.disconnect(on_pin_entry_proceed); + if (!is_running()) return; - debug("EVENT: web pane has loaded a page, need to check if auth token has become valid"); - do_token_check(); + debug("EVENT: user clicked 'Continue' in PIN entry pane."); + + do_verify_pin(pin); } - private void on_token_check_txn_completed(Publishing.RESTSupport.Transaction txn) { - txn.completed.disconnect(on_token_check_txn_completed); - txn.network_error.disconnect(on_token_check_txn_error); - + private void on_access_token_fetch_txn_completed(Publishing.RESTSupport.Transaction txn) { + txn.completed.disconnect(on_access_token_fetch_txn_completed); + txn.network_error.disconnect(on_access_token_fetch_error); + if (!is_running()) return; - - debug("EVENT: token check transaction response received over the network"); - do_interpret_token_check_xml(txn.get_response()); + + debug("EVENT: fetching OAuth access token over the network succeeded"); + + do_extract_access_phase_credentials_from_reponse(txn.get_response()); } - // token check "error" vs "failure" -- "error" means that the actual network transaction - // errored out, indicating a network transport issue such as bad DNS lookup, 404 error, etc., - // whereas "failure" means that the network transaction succeeded in making a round trip - // to the server but the response didn't contain an authentication token - - private void on_token_check_txn_error(Publishing.RESTSupport.Transaction txn, + private void on_access_token_fetch_error(Publishing.RESTSupport.Transaction txn, Spit.Publishing.PublishingError err) { - txn.completed.disconnect(on_token_check_txn_completed); - txn.network_error.disconnect(on_token_check_txn_error); - + txn.completed.disconnect(on_access_token_fetch_txn_completed); + txn.network_error.disconnect(on_access_token_fetch_error); + if (!is_running()) return; - debug("EVENT: token check transaction caused a network error"); - + debug("EVENT: fetching OAuth access token over the network caused an error."); + host.post_error(err); } - - private void on_token_check_failed() { - if (!is_running()) - return; - - debug("EVENT: checked response XML for token but one isn't available yet"); - do_continue_hosted_web_authentication(); - } - - private void on_token_check_succeeded(string token, string username) { - if (!is_running()) - return; - - debug("EVENT: auth token = '%s' for username = '%s' has become available.", token, username); - do_authenticate_session(token, username); - } - private void on_authenticated_session_ready() { + private void on_session_authenticated() { if (!is_running()) return; - debug("EVENT: an authenticated session has become available"); + debug("EVENT: a fully authenticated session has become available"); + parameters.username = session.get_username(); + + set_persistent_access_phase_token(session.get_access_phase_token()); + set_persistent_access_phase_token_secret(session.get_access_phase_token_secret()); + set_persistent_access_phase_username(session.get_username()); + do_fetch_account_info(); } @@ -283,6 +292,9 @@ } private void on_publishing_options_pane_publish() { + publishing_options_pane.publish.disconnect(on_publishing_options_pane_publish); + publishing_options_pane.logout.disconnect(on_publishing_options_pane_logout); + if (!is_running()) return; @@ -291,6 +303,9 @@ } private void on_publishing_options_pane_logout() { + publishing_options_pane.publish.disconnect(on_publishing_options_pane_publish); + publishing_options_pane.logout.disconnect(on_publishing_options_pane_logout); + if (!is_running()) return; @@ -342,157 +357,128 @@ host.set_service_locked(false); host.install_welcome_pane(SERVICE_WELCOME_MESSAGE, on_welcome_pane_login_clicked); } - - private void do_obtain_frob() { - debug("ACTION: running network transaction to obtain Yahoo! login frob"); + + private void do_run_authentication_request_transaction() { + debug("ACTION: running authentication request transaction"); host.set_service_locked(true); - host.install_static_message_pane(_("Preparing to login...")); - - FrobFetchTransaction frob_fetch_txn = new FrobFetchTransaction(session); - frob_fetch_txn.completed.connect(on_frob_fetch_txn_completed); - frob_fetch_txn.network_error.connect(on_frob_fetch_txn_error); + host.install_static_message_pane(_("Preparing for login...")); + AuthenticationRequestTransaction txn = new AuthenticationRequestTransaction(session); + txn.completed.connect(on_auth_request_txn_completed); + txn.network_error.connect(on_auth_request_txn_error); + try { - frob_fetch_txn.execute(); + txn.execute(); } catch (Spit.Publishing.PublishingError err) { host.post_error(err); } } - - private void do_extract_frob_from_xml(string xml) { - debug("ACTION: extracting Yahoo! login frob from response xml = '%s'", xml); - string frob = null; - try { - Publishing.RESTSupport.XmlDocument response_doc = Transaction.parse_flickr_response(xml); - - Xml.Node* root = response_doc.get_root_node(); - - Xml.Node* frob_node = response_doc.get_named_child(root, "frob"); - - string local_frob = frob_node->get_content(); - - if (local_frob == null) - throw new Spit.Publishing.PublishingError.MALFORMED_RESPONSE("No frob returned " + - "in request"); + + private void do_parse_token_info_from_auth_request(string response) { + debug("ACTION: parsing authorization request response '%s' into token and secret", response); + + string? oauth_token = null; + string? oauth_token_secret = null; + + string[] key_value_pairs = response.split("&"); + foreach (string pair in key_value_pairs) { + string[] split_pair = pair.split("="); - frob = local_frob; - } catch (Spit.Publishing.PublishingError err) { - host.post_error(err); - return; + if (split_pair.length != 2) + host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE( + "'%s' isn't a valid response to an OAuth authentication request")); + + if (split_pair[0] == "oauth_token") + oauth_token = split_pair[1]; + else if (split_pair[0] == "oauth_token_secret") + oauth_token_secret = split_pair[1]; } - assert(frob != null); - this.frob = frob; - on_frob_available(frob); + if (oauth_token == null || oauth_token_secret == null) + host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE( + "'%s' isn't a valid response to an OAuth authentication request")); + + + on_authentication_token_available(oauth_token, oauth_token_secret); } - - private void do_build_login_url_from_frob(string frob) { - debug("ACTION: building hosted web login url from frob"); - - string hash_string = session.get_api_secret() + "api_key%s".printf(session.get_api_key()) + - "frob%s".printf(frob) + "permswrite"; - string sig = Checksum.compute_for_string(ChecksumType.MD5, hash_string); - string login_url = - "http://flickr.com/services/auth/?api_key=%s&perms=%s&frob=%s&api_sig=%s".printf( - session.get_api_key(), "write", frob, sig); - - on_login_url_available(login_url); + + private void do_launch_system_browser(string token) { + string login_uri = "http://www.flickr.com/services/oauth/authorize?oauth_token=" + token + + "&perms=write"; + + debug("ACTION: launching system browser with uri = '%s'", login_uri); + + try { + Process.spawn_command_line_async("xdg-open " + login_uri); + } catch (SpawnError e) { + host.post_error(new Spit.Publishing.PublishingError.LOCAL_FILE_ERROR( + "couldn't launch system web browser to complete Flickr login")); + return; + } + + on_system_browser_launched(); } - - private void do_start_hosted_web_authentication(string login_url) { - debug("ACTION: running hosted web login"); + + private void do_show_pin_entry_pane() { + debug("ACTION: showing PIN entry pane"); - host.set_service_locked(false); - - web_auth_pane = new WebAuthenticationPane(login_url); - web_auth_pane.token_check_required.connect(on_web_auth_pane_token_check_required); - host.install_dialog_pane(web_auth_pane); + PinEntryPane pin_entry_pane = new PinEntryPane(); + pin_entry_pane.proceed.connect(on_pin_entry_proceed); + host.install_dialog_pane(pin_entry_pane); } - - private void do_token_check() { - // if the session is already authenticated, then we have a valid token, so do nothing - if (session.is_authenticated()) - return; - - debug("ACTION: running network transaction to check if auth token has become available"); + + private void do_verify_pin(string pin) { + debug("ACTION: validating authorization PIN %s", pin); + + host.set_service_locked(true); + host.install_static_message_pane(_("Verifying authorization...")); - TokenCheckTransaction token_check_txn = new TokenCheckTransaction(session, frob); - token_check_txn.completed.connect(on_token_check_txn_completed); - token_check_txn.network_error.connect(on_token_check_txn_error); + AccessTokenFetchTransaction txn = new AccessTokenFetchTransaction(session, pin); + txn.completed.connect(on_access_token_fetch_txn_completed); + txn.network_error.connect(on_access_token_fetch_error); try { - token_check_txn.execute(); + txn.execute(); } catch (Spit.Publishing.PublishingError err) { host.post_error(err); } } + + private void do_extract_access_phase_credentials_from_reponse(string response) { + debug("ACTION: extracting access phase credentials from '%s'", response); + + string[] key_value_pairs = response.split("&"); - private void do_interpret_token_check_xml(string xml) { - // if the session is already authenticated, then we have a valid token, so do nothing - if (session.is_authenticated()) - return; + string? token = null; + string? token_secret = null; + string? username = null; + foreach (string key_value_pair in key_value_pairs) { + string[] split_pair = key_value_pair.split("="); - debug("ACTION: checking response XML to see if it contains an auth token; xml = '%s'", xml); + if (split_pair.length != 2) + continue; - Publishing.RESTSupport.XmlDocument response_doc = null; - try { - response_doc = Transaction.parse_flickr_response(xml); - } catch (Spit.Publishing.PublishingError err) { - // if we get a service error during token check, it is recoverable -- it just means - // that no authentication token is available yet -- so just spawn an event for it - // and return - if (err is Spit.Publishing.PublishingError.SERVICE_ERROR) { - on_token_check_failed(); - return; - } + string key = split_pair[0]; + string value = split_pair[1]; - host.post_error(err); - return; - } - - string token = null; - string username = null; - - try { - Xml.Node* response_doc_root = response_doc.get_root_node(); - - // search through the top-level child nodes looking for a node named '': - // all authentication information is packaged within this node - Xml.Node* auth_node = response_doc.get_named_child(response_doc_root, "auth"); - - // search through the children of the '' node looking for the '' and '' - // nodes - Xml.Node* token_node = response_doc.get_named_child(auth_node, "token"); - Xml.Node* user_node = response_doc.get_named_child(auth_node, "user"); - - token = token_node->children->content; - username = response_doc.get_property_value(user_node, "username"); - } catch (Spit.Publishing.PublishingError err) { - host.post_error(err); - return; + if (key == "oauth_token") + token = value; + else if (key == "oauth_token_secret") + token_secret = value; + else if (key == "username") + username = value; } - assert((token != null) && (username != null)); - web_auth_pane.interaction_completed(); - on_token_check_succeeded(token, username); - } - - private void do_continue_hosted_web_authentication() { - debug("ACTION: continuing hosted web authentication"); - assert(web_auth_pane != null); - web_auth_pane.show_page(); - } - - private void do_authenticate_session(string token, string username) { - debug("ACTION: authenicating session"); - - session.authenticate(token, username); - assert(session.is_authenticated()); - set_persistent_auth_token(token); - set_persistent_username(username); + debug("access phase credentials: { token = '%s'; token_secret = '%s'; username = '%s' }", + token, token_secret, username); + + if (token == null || token_secret == null || username == null) + host.post_error(new Spit.Publishing.PublishingError.MALFORMED_RESPONSE("expected " + + "access phase credentials to contain token, token secret, and username but at " + + "least one of these is absent")); - on_authenticated_session_ready(); + session.set_access_phase_credentials(token, token_secret, username); } private void do_fetch_account_info() { @@ -552,10 +538,13 @@ host.post_error(err); return; } + on_account_info_available(); } private void do_logout() { + debug("ACTION: logging user out, deauthenticating session, and erasing stored credentials"); + session.deauthenticate(); invalidate_persistent_session(); @@ -566,9 +555,10 @@ private void do_show_publishing_options_pane() { debug("ACTION: displaying publishing options pane"); + host.set_service_locked(false); - PublishingOptionsPane publishing_options_pane = new PublishingOptionsPane(this, parameters, + publishing_options_pane = new PublishingOptionsPane(this, parameters, host.get_publishable_media_type()); publishing_options_pane.publish.connect(on_publishing_options_pane_publish); publishing_options_pane.logout.connect(on_publishing_options_pane_logout); @@ -646,13 +636,13 @@ was_started = true; if (is_persistent_session_valid()) { - session.authenticate(get_persistent_auth_token(), get_persistent_username()); - on_authenticated_session_ready(); - } else if (WebAuthenticationPane.is_cache_dirty()) { - host.set_service_locked(false); - host.install_static_message_pane(RESTART_ERROR_MESSAGE, - Spit.Publishing.PluginHost.ButtonMode.CLOSE); + debug("attempt start: a persistent session is available; using it"); + + session.authenticate_from_persistent_credentials(get_persistent_access_phase_token(), + get_persistent_access_phase_token_secret(), get_persistent_access_phase_username()); } else { + debug("attempt start: no persistent session available; showing login welcome pane"); + do_show_login_welcome_pane(); } } @@ -679,33 +669,116 @@ } } -internal class Transaction : Publishing.RESTSupport.Transaction { - public const string SIGNATURE_KEY = "api_sig"; +internal class PinEntryPane : Spit.Publishing.DialogPane, GLib.Object { + private Gtk.Widget? widget = null; + private Gtk.Button? continue_button = null; + private Gtk.Entry? pin_entry = null; + + public signal void proceed(PinEntryPane sender, string authorization_pin); + + public PinEntryPane() { + Gtk.VBox pane_wrapper = new Gtk.VBox(false, 8); + Gtk.Label explanatory_text = new Gtk.Label(_("Enter the confirmation number which appears after you log into Flickr in your Web browser")); - public Transaction(Session session) { - base(session); + pane_wrapper.add(explanatory_text); + + Gtk.HBox pin_entry_wrapper = new Gtk.HBox(false, 12); + + Gtk.Label pin_entry_caption = new Gtk.Label.with_mnemonic(_("Authorization _Number:")); + + pin_entry = new Gtk.Entry(); + + pin_entry_caption.set_mnemonic_widget(pin_entry); + + Gtk.SeparatorToolItem h_spacer1 = new Gtk.SeparatorToolItem(); + h_spacer1.set_size_request(48, -1); + h_spacer1.set_draw(false); + + Gtk.SeparatorToolItem h_spacer2 = new Gtk.SeparatorToolItem(); + h_spacer2.set_size_request(58, -1); + h_spacer2.set_draw(false); + + pin_entry_wrapper.add(h_spacer1); + pin_entry_wrapper.add(pin_entry_caption); + pin_entry_wrapper.add(pin_entry); + pin_entry_wrapper.add(h_spacer2); + + pane_wrapper.add(pin_entry_wrapper); + + continue_button = new Gtk.Button.with_mnemonic(_("Con_tinue")); + continue_button.set_size_request(92, -1); + Gtk.Alignment continue_button_wrapper = new Gtk.Alignment(0.5f, 0.5f, 0.0f, 0.0f); + continue_button_wrapper.add(continue_button); + + pane_wrapper.add(continue_button_wrapper); + + Gtk.SeparatorToolItem v_spacer2 = new Gtk.SeparatorToolItem(); + v_spacer2.set_size_request(-1, 80); + v_spacer2.set_draw(false); + pane_wrapper.add(v_spacer2); + + widget = pane_wrapper; + + widget.show_all(); + + on_pin_entry_contents_changed(); + } + + private void on_continue_clicked() { + proceed(this, pin_entry.get_text()); + } + + private void on_pin_entry_contents_changed() { + continue_button.set_sensitive(pin_entry.text_length > 0); + } - add_argument("api_key", ((Session) get_parent_session()).get_api_key()); + public Gtk.Widget get_widget() { + return widget; } - private void sign() { - string sig = generate_signature(get_sorted_arguments(), - ((Session) get_parent_session()).get_api_secret()); + public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() { + return Spit.Publishing.DialogPane.GeometryOptions.NONE; + } - add_argument(SIGNATURE_KEY, sig); + public void on_pane_installed() { + continue_button.clicked.connect(on_continue_clicked); + pin_entry.changed.connect(on_pin_entry_contents_changed); } - public static string generate_signature(Publishing.RESTSupport.Argument[] sorted_args, - string api_secret) { - string hash_string = ""; - foreach (Publishing.RESTSupport.Argument arg in sorted_args) - hash_string = hash_string + ("%s%s".printf(arg.key, arg.value)); + public void on_pane_uninstalled() { + continue_button.clicked.disconnect(on_continue_clicked); + pin_entry.changed.disconnect(on_pin_entry_contents_changed); + } +} - return Checksum.compute_for_string(ChecksumType.MD5, api_secret + hash_string); +internal class Transaction : Publishing.RESTSupport.Transaction { + public Transaction(Session session, Publishing.RESTSupport.HttpMethod method = + Publishing.RESTSupport.HttpMethod.POST) { + base(session, method); + + add_argument("oauth_nonce", session.get_oauth_nonce()); + add_argument("oauth_signature_method", "HMAC-SHA1"); + add_argument("oauth_version", "1.0"); + add_argument("oauth_callback", "oob"); + add_argument("oauth_timestamp", session.get_oauth_timestamp()); + add_argument("oauth_consumer_key", API_KEY); + } + + public Transaction.with_uri(Session session, string uri, + Publishing.RESTSupport.HttpMethod method = Publishing.RESTSupport.HttpMethod.POST) { + base.with_endpoint_url(session, uri, method); + + add_argument("oauth_nonce", session.get_oauth_nonce()); + add_argument("oauth_signature_method", "HMAC-SHA1"); + add_argument("oauth_version", "1.0"); + add_argument("oauth_callback", "oob"); + add_argument("oauth_timestamp", session.get_oauth_timestamp()); + add_argument("oauth_consumer_key", API_KEY); } public override void execute() throws Spit.Publishing.PublishingError { - sign(); + ((Session) get_parent_session()).sign_transaction(this); + base.execute(); } @@ -758,43 +831,51 @@ } } -internal class FrobFetchTransaction : Transaction { - public FrobFetchTransaction(Session session) { - base(session); - - add_argument("method", "flickr.auth.getFrob"); +internal class AuthenticationRequestTransaction : Transaction { + public AuthenticationRequestTransaction(Session session) { + base.with_uri(session, "http://www.flickr.com/services/oauth/request_token", + Publishing.RESTSupport.HttpMethod.GET); } } -internal class TokenCheckTransaction : Transaction { - public TokenCheckTransaction(Session session, string frob) { - base(session); - - add_argument("method", "flickr.auth.getToken"); - add_argument("frob", frob); +internal class AccessTokenFetchTransaction : Transaction { + public AccessTokenFetchTransaction(Session session, string user_verifier) { + base.with_uri(session, "http://www.flickr.com/services/oauth/access_token", + Publishing.RESTSupport.HttpMethod.GET); + add_argument("oauth_verifier", user_verifier); + add_argument("oauth_token", session.get_request_phase_token()); } } internal class AccountInfoFetchTransaction : Transaction { public AccountInfoFetchTransaction(Session session) { - base(session); - + base(session, Publishing.RESTSupport.HttpMethod.GET); add_argument("method", "flickr.people.getUploadStatus"); - add_argument("auth_token", session.get_auth_token()); + add_argument("oauth_token", session.get_access_phase_token()); } } private class UploadTransaction : Publishing.RESTSupport.UploadTransaction { private PublishingParameters parameters; + private Session session; + private Publishing.RESTSupport.Argument[] auth_header_fields; public UploadTransaction(Session session, PublishingParameters parameters, Spit.Publishing.Publishable publishable) { base.with_endpoint_url(session, publishable, "http://api.flickr.com/services/upload"); this.parameters = parameters; + this.session = session; + this.auth_header_fields = new Publishing.RESTSupport.Argument[0]; - add_argument("api_key", session.get_api_key()); - add_argument("auth_token", session.get_auth_token()); + add_authorization_header_field("oauth_nonce", session.get_oauth_nonce()); + add_authorization_header_field("oauth_signature_method", "HMAC-SHA1"); + add_authorization_header_field("oauth_version", "1.0"); + add_authorization_header_field("oauth_callback", "oob"); + add_authorization_header_field("oauth_timestamp", session.get_oauth_timestamp()); + add_authorization_header_field("oauth_consumer_key", API_KEY); + add_authorization_header_field("oauth_token", session.get_access_phase_token()); + add_argument("is_public", ("%d".printf(parameters.visibility_specification.everyone_level))); add_argument("is_friend", ("%d".printf(parameters.visibility_specification.friends_level))); add_argument("is_family", ("%d".printf(parameters.visibility_specification.family_level))); @@ -804,150 +885,212 @@ string? filename = publishable.get_publishing_name(); if (filename == null || filename == "") filename = publishable.get_param_string(Spit.Publishing.Publishable.PARAM_STRING_BASENAME); - disposition_table.insert("filename", Soup.URI.encode(filename, "'")); + disposition_table.insert("filename", Soup.URI.encode(filename, "")); disposition_table.insert("name", "photo"); set_binary_disposition_table(disposition_table); } + public void add_authorization_header_field(string key, string value) { + auth_header_fields += new Publishing.RESTSupport.Argument(key, value); + } + + public Publishing.RESTSupport.Argument[] get_authorization_header_fields() { + return auth_header_fields; + } + + public string get_authorization_header_string() { + string result = "OAuth "; + + for (int i = 0; i < auth_header_fields.length; i++) { + result += auth_header_fields[i].key; + result += "="; + result += ("\"" + auth_header_fields[i].value + "\""); + + if (i < auth_header_fields.length - 1) + result += ", "; + } + + return result; + } + public override void execute() throws Spit.Publishing.PublishingError { - string sig = Transaction.generate_signature(get_sorted_arguments(), - ((Session) get_parent_session()).get_api_secret()); - - add_argument(Transaction.SIGNATURE_KEY, sig); + session.sign_transaction(this); + + string authorization_header = get_authorization_header_string(); + + debug("executing upload transaction: authorization header string = '%s'", + authorization_header); + add_header("Authorization", authorization_header); base.execute(); } } internal class Session : Publishing.RESTSupport.Session { - private string api_key; - private string api_secret; - private string? auth_token = null; + private string? request_phase_token = null; + private string? request_phase_token_secret = null; + private string? access_phase_token = null; + private string? access_phase_token_secret = null; private string? username = null; public Session() { base(ENDPOINT_URL); - - this.api_key = API_KEY; - this.api_secret = API_SECRET; } public override bool is_authenticated() { - return (auth_token != null && username != null); + return (access_phase_token != null && access_phase_token_secret != null && + username != null); } - public void authenticate(string auth_token, string username) { - this.auth_token = auth_token; + public void authenticate_from_persistent_credentials(string token, string secret, + string username) { + this.access_phase_token = token; + this.access_phase_token_secret = secret; this.username = username; + + authenticated(); } - + public void deauthenticate() { + access_phase_token = null; + access_phase_token_secret = null; username = null; - auth_token = null; - } - - public string get_api_key() { - return api_key; } - public string get_api_secret() { - return api_secret; - } + public void sign_transaction(Publishing.RESTSupport.Transaction txn) { + string http_method = txn.get_method().to_string(); + + debug("signing transaction with parameters:"); + debug("HTTP method = " + http_method); - public string get_auth_token() { - assert(is_authenticated()); - return auth_token; - } + Publishing.RESTSupport.Argument[] base_string_arguments = txn.get_arguments(); - public string get_username() { - assert(is_authenticated()); - return username; - } -} + UploadTransaction? upload_txn = txn as UploadTransaction; + if (upload_txn != null) { + debug("this transaction is an UploadTransaction; including Authorization header " + + "fields in signature base string"); + + Publishing.RESTSupport.Argument[] auth_header_args = + upload_txn.get_authorization_header_fields(); -internal class WebAuthenticationPane : Spit.Publishing.DialogPane, Object { - private const string END_STAGE_URL = "http://www.flickr.com/services/auth/"; + foreach (Publishing.RESTSupport.Argument arg in auth_header_args) + base_string_arguments += arg; + } + + Publishing.RESTSupport.Argument[] sorted_args = + Publishing.RESTSupport.Argument.sort(base_string_arguments); + + string arguments_string = ""; + for (int i = 0; i < sorted_args.length; i++) { + arguments_string += (sorted_args[i].key + "=" + sorted_args[i].value); + if (i < sorted_args.length - 1) + arguments_string += "&"; + } - private static bool cache_dirty = false; + string? signing_key = null; + if (access_phase_token_secret != null) { + debug("access phase token secret available; using it as signing key"); + + signing_key = API_SECRET + "&" + access_phase_token_secret; + } else if (request_phase_token_secret != null) { + debug("request phase token secret available; using it as signing key"); - private WebKit.WebView webview = null; - private Gtk.ScrolledWindow webview_frame = null; - private Gtk.Container white_pane = null; - private string login_url; - private Gtk.VBox pane_widget = null; - - public signal void token_check_required(); - - public WebAuthenticationPane(string login_url) { - this.pane_widget = new Gtk.VBox(false, 0); - this.login_url = login_url; - - Gdk.Color white_color; - Gdk.Color.parse("white", out white_color); - white_pane = new Gtk.EventBox(); - white_pane.modify_bg(Gtk.StateType.NORMAL, white_color); - white_pane.modify_base(Gtk.StateType.NORMAL, white_color); - pane_widget.add(white_pane); - - webview_frame = new Gtk.ScrolledWindow(null, null); - webview_frame.set_shadow_type(Gtk.ShadowType.ETCHED_IN); - webview_frame.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); - - webview = new WebKit.WebView(); - webview.get_settings().enable_plugins = false; - webview.get_settings().enable_default_context_menu = false; - - webview.load_finished.connect(on_load_finished); - webview.load_started.connect(on_load_started); - - webview_frame.add(webview); - white_pane.add(webview_frame); - white_pane.set_size_request(820, 578); - webview.set_size_request(840, 578); - } - - - private void on_load_finished(WebKit.WebFrame origin_frame) { - if (origin_frame.uri == END_STAGE_URL) { - token_check_required(); + signing_key = API_SECRET + "&" + request_phase_token_secret; } else { - show_page(); + debug("neither access phase nor request phase token secrets available; using API " + + "key as signing key"); + + signing_key = API_SECRET + "&"; } + + string signature_base_string = http_method + "&" + Soup.URI.encode( + txn.get_endpoint_url(), ENCODE_RFC_3986_EXTRA) + "&" + + Soup.URI.encode(arguments_string, ENCODE_RFC_3986_EXTRA); + + debug("signature base string = '%s'", signature_base_string); + + debug("signing key = '%s'", signing_key); + + // compute the signature + string signature = compute_hmac_for_string(ChecksumType.SHA1, signing_key, + signing_key.length, signature_base_string, signature_base_string.length); + + // Now that we've got the signature, go through all manner of encoding shenanigans -- from + // hex to ASCII to Base64 then percent-encoded with overrides to transform the signature + // into the format Yahoo! wants + signature = hex_to_ascii(signature); + signature = Base64.encode(signature.data); + signature = Soup.URI.encode(signature, ENCODE_RFC_3986_EXTRA); + + debug("request signature = '%s'", signature); + + if (upload_txn != null) + upload_txn.add_authorization_header_field("oauth_signature", signature); + else + txn.add_argument("oauth_signature", signature); } - private void on_load_started(WebKit.WebFrame origin_frame) { - webview.hide(); - pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.WATCH)); + public void set_request_phase_credentials(string token, string secret) { + this.request_phase_token = token; + this.request_phase_token_secret = secret; } - - public static bool is_cache_dirty() { - return cache_dirty; + + public void set_access_phase_credentials(string token, string secret, string username) { + this.access_phase_token = token; + this.access_phase_token_secret = secret; + this.username = username; + + authenticated(); } - public void show_page() { - webview.show(); - pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR)); + public string get_oauth_nonce() { + TimeVal currtime = TimeVal(); + currtime.get_current_time(); + + return Checksum.compute_for_string(ChecksumType.MD5, currtime.tv_sec.to_string() + + currtime.tv_usec.to_string()); } - - public void interaction_completed() { - cache_dirty = true; - pane_widget.get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR)); + + public string get_oauth_timestamp() { + return GLib.get_real_time().to_string().substring(0, 10); } - public Gtk.Widget get_widget() { - return pane_widget; + public string get_request_phase_token() { + assert(request_phase_token != null); + return request_phase_token; } - public Spit.Publishing.DialogPane.GeometryOptions get_preferred_geometry() { - return Spit.Publishing.DialogPane.GeometryOptions.EXTENDED_SIZE; + public string get_access_phase_token() { + assert(access_phase_token != null); + return access_phase_token; } - public void on_pane_installed() { - webview.open(login_url); + public string get_access_phase_token_secret() { + assert(access_phase_token_secret != null); + return access_phase_token_secret; } - public void on_pane_uninstalled() { + private static string hex_to_ascii(string s) { + assert(s.length % 2 == 0); + + string result = ""; + + for (int window_start = 0; window_start < s.length; window_start += 2) { + string window = "0x" + s.substring(window_start, 2); + + int n = 0; + window.scanf("%x", &n); + + result += "%c".printf((char) n); + } + + return result; + } + + public string get_username() { + assert(is_authenticated()); + return username; } } @@ -1026,7 +1169,8 @@ string visibility_label_text = _("Photos _visible to:"); if ((media_type == Spit.Publishing.Publisher.MediaType.VIDEO)) { visibility_label_text = _("Videos _visible to:"); - } else if ((media_type == (Spit.Publishing.Publisher.MediaType.PHOTO | Spit.Publishing.Publisher.MediaType.VIDEO))) { + } else if ((media_type == (Spit.Publishing.Publisher.MediaType.PHOTO | + Spit.Publishing.Publisher.MediaType.VIDEO))) { visibility_label_text = _("Photos and videos _visible to:"); } Gtk.Label visibility_label = new Gtk.Label.with_mnemonic(visibility_label_text); diff -Nru shotwell-0.11.91/plugins/shotwell-publishing/Makefile shotwell-0.11.92/plugins/shotwell-publishing/Makefile --- shotwell-0.11.91/plugins/shotwell-publishing/Makefile 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing/Makefile 2012-02-20 20:47:27.000000000 +0000 @@ -23,5 +23,8 @@ picasa.png \ youtube.png +CUSTOM_VAPI_PKGS := \ + hmac-glib + include ../Makefile.plugin.mk diff -Nru shotwell-0.11.91/plugins/shotwell-publishing/PicasaPublishing.vala shotwell-0.11.92/plugins/shotwell-publishing/PicasaPublishing.vala --- shotwell-0.11.91/plugins/shotwell-publishing/PicasaPublishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing/PicasaPublishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -29,7 +29,7 @@ public void get_info(ref Spit.PluggableInfo info) { info.authors = "Lucas Beeler"; - info.copyright = _("Copyright 2009-2011 Yorba Foundation"); + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); info.translators = Resources.TRANSLATORS; info.version = _VERSION; info.website_name = Resources.WEBSITE_NAME; diff -Nru shotwell-0.11.91/plugins/shotwell-publishing/shotwell-publishing.vala shotwell-0.11.92/plugins/shotwell-publishing/shotwell-publishing.vala --- shotwell-0.11.91/plugins/shotwell-publishing/shotwell-publishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing/shotwell-publishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/plugins/shotwell-publishing/YouTubePublishing.vala shotwell-0.11.92/plugins/shotwell-publishing/YouTubePublishing.vala --- shotwell-0.11.91/plugins/shotwell-publishing/YouTubePublishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing/YouTubePublishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -29,7 +29,7 @@ public void get_info(ref Spit.PluggableInfo info) { info.authors = "Jani Monoses"; - info.copyright = _("Copyright 2009-2011 Yorba Foundation"); + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); info.translators = Resources.TRANSLATORS; info.version = _VERSION; info.website_name = Resources.WEBSITE_NAME; diff -Nru shotwell-0.11.91/plugins/shotwell-publishing-extras/piwigo_authentication_pane.glade shotwell-0.11.92/plugins/shotwell-publishing-extras/piwigo_authentication_pane.glade --- shotwell-0.11.91/plugins/shotwell-publishing-extras/piwigo_authentication_pane.glade 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing-extras/piwigo_authentication_pane.glade 2012-02-20 20:47:27.000000000 +0000 @@ -1,36 +1,50 @@ - + False True + False 0.5 0.5 True + False + 30 + 30 + True + 8 True + False + True + True 0 label True False + True 0 True + False 3 2 + 8 + 2 True + False 0 _URL of your Piwigo photo library True @@ -40,6 +54,7 @@ True + False 0 User _name True @@ -53,6 +68,7 @@ True + False 0 _Password True @@ -104,6 +120,8 @@ + True + True 1 @@ -113,22 +131,28 @@ True True False + False True + 0 True + True + True 2 True + False Login True True True + False False @@ -138,6 +162,8 @@ + True + True 3 diff -Nru shotwell-0.11.91/plugins/shotwell-publishing-extras/PiwigoPublishing.vala shotwell-0.11.92/plugins/shotwell-publishing-extras/PiwigoPublishing.vala --- shotwell-0.11.91/plugins/shotwell-publishing-extras/PiwigoPublishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing-extras/PiwigoPublishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -30,7 +30,7 @@ public void get_info(ref Spit.PluggableInfo info) { info.authors = "Bruno Girin"; - info.copyright = _("Copyright 2009-2011 Yorba Foundation"); + info.copyright = _("Copyright 2009-2012 Yorba Foundation"); info.translators = Resources.TRANSLATORS; info.version = _VERSION; info.website_name = Resources.WEBSITE_NAME; @@ -64,6 +64,8 @@ // and handle older version of the Piwigo API internal const string ERROR_MESSAGE_501 = _("The Piwigo service you specified does not recognise the method requested by Shotwell. This can happen if the Piwigo service you are trying to publish to is an old version. Please check that your Piwigo service is version 2.1 or newer."); +internal const string ERROR_MESSAGE_GENERIC = + _("An error message occured when publishing to Piwigo. Please try again."); internal const int ORIGINAL_SIZE = -1; internal class Category { @@ -307,6 +309,7 @@ try { login_trans.execute(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: do_network_login"); do_show_error(err); } } @@ -357,8 +360,10 @@ } catch (Spit.Publishing.PublishingError code) { int code_int = int.parse(code.message); if (code_int == 999) { + debug("ERROR: on_login_network_complete, code 999"); do_show_authentication_pane(AuthenticationPane.Mode.FAILED_RETRY_USER); } else { + debug("ERROR: on_login_network_complete"); do_show_error(err); } } @@ -423,6 +428,7 @@ try { status_txn.execute(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: do_fetch_session_status, not authenticated"); do_show_error(err); } } else { @@ -433,6 +439,7 @@ try { status_txn.execute(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: do_fetch_session_status, authenticated"); do_show_error(err); } } @@ -470,10 +477,12 @@ set_persistent_username(session.get_username()); do_fetch_categories(); } catch (Spit.Publishing.PublishingError err2) { + debug("ERROR: on_session_get_status_complete, inner"); do_show_error(err2); return; } } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: on_session_get_status_complete, outer"); do_show_error(err); return; } @@ -516,6 +525,7 @@ try { cat_trans.execute(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: do_fetch_categories"); do_show_error(err); } } @@ -557,6 +567,7 @@ categories += new Category(int.parse(id_string), name); } } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: on_category_fetch_complete"); do_show_error(err); return; } @@ -608,6 +619,7 @@ try { logout_trans.execute(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: on_publishing_options_pane_logout_clicked"); do_show_error(err); } } @@ -688,6 +700,7 @@ try { creation_trans.execute(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: do_create_category"); do_show_error(err); } } @@ -717,6 +730,7 @@ parameters.category.id = id; do_upload(); } catch (Spit.Publishing.PublishingError err) { + debug("ERROR: on_category_add_complete"); do_show_error(err); } } @@ -816,26 +830,41 @@ Spit.Publishing.PublishingError err ) { debug("EVENT: on_network_error"); - // TODO: add more special error cases as and when required - if(err.message.has_prefix("401")) - do_show_error_message(ERROR_MESSAGE_401); - else if(err.message.has_prefix("501")) - do_show_error_message(ERROR_MESSAGE_501); - else - do_show_error(err); + do_show_error(err); } /** * Action to display an error to the user. */ private void do_show_error(Spit.Publishing.PublishingError e) { - do_show_error_message(e.message); + debug("ACTION: do_show_error"); + string error_type = "UNKNOWN"; + if (e is Spit.Publishing.PublishingError.NO_ANSWER) { + do_show_authentication_pane(AuthenticationPane.Mode.FAILED_RETRY_URL); + return; + } else if(e is Spit.Publishing.PublishingError.COMMUNICATION_FAILED) { + error_type = "COMMUNICATION_FAILED"; + } else if(e is Spit.Publishing.PublishingError.PROTOCOL_ERROR) { + error_type = "PROTOCOL_ERROR"; + } else if(e is Spit.Publishing.PublishingError.SERVICE_ERROR) { + error_type = "SERVICE_ERROR"; + } else if(e is Spit.Publishing.PublishingError.MALFORMED_RESPONSE) { + error_type = "MALFORMED_RESPONSE"; + } else if(e is Spit.Publishing.PublishingError.LOCAL_FILE_ERROR) { + error_type = "LOCAL_FILE_ERROR"; + } else if(e is Spit.Publishing.PublishingError.EXPIRED_SESSION) { + error_type = "EXPIRED_SESSION"; + } + + debug("Unhandled error: type=%s; message='%s'".printf(error_type, e.message)); + do_show_error_message(ERROR_MESSAGE_GENERIC); } /** * Action to display an error message to the user. */ private void do_show_error_message(string message) { + debug("ACTION: do_show_error_message"); host.install_static_message_pane(message, Spit.Publishing.PluginHost.ButtonMode.CLOSE); } diff -Nru shotwell-0.11.91/plugins/shotwell-publishing-extras/shotwell-publishing-extras.vala shotwell-0.11.92/plugins/shotwell-publishing-extras/shotwell-publishing-extras.vala --- shotwell-0.11.91/plugins/shotwell-publishing-extras/shotwell-publishing-extras.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-publishing-extras/shotwell-publishing-extras.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/plugins/shotwell-transitions/CrumbleEffect.vala shotwell-0.11.92/plugins/shotwell-transitions/CrumbleEffect.vala --- shotwell-0.11.91/plugins/shotwell-transitions/CrumbleEffect.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-transitions/CrumbleEffect.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright 2010 Maxim Kartashev - * Copyright 2011 Yorba Foundation + * Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/plugins/shotwell-transitions/FadeEffect.vala shotwell-0.11.92/plugins/shotwell-transitions/FadeEffect.vala --- shotwell-0.11.91/plugins/shotwell-transitions/FadeEffect.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-transitions/FadeEffect.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright 2010 Maxim Kartashev - * Copyright 2011 Yorba Foundation + * Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/plugins/shotwell-transitions/shotwell-transitions.vala shotwell-0.11.92/plugins/shotwell-transitions/shotwell-transitions.vala --- shotwell-0.11.91/plugins/shotwell-transitions/shotwell-transitions.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-transitions/shotwell-transitions.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -65,7 +65,7 @@ public void get_info(ref Spit.PluggableInfo info) { info.authors = "Maxim Kartashev"; - info.copyright = _("Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation"); + info.copyright = _("Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation"); info.translators = Resources.TRANSLATORS; info.version = _VERSION; info.website_name = Resources.WEBSITE_NAME; diff -Nru shotwell-0.11.91/plugins/shotwell-transitions/SlideEffect.vala shotwell-0.11.92/plugins/shotwell-transitions/SlideEffect.vala --- shotwell-0.11.91/plugins/shotwell-transitions/SlideEffect.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/plugins/shotwell-transitions/SlideEffect.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright 2010 Maxim Kartashev - * Copyright 2011 Yorba Foundation + * Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/po/shotwell-core/ar.po shotwell-0.11.92/po/shotwell-core/ar.po --- shotwell-0.11.91/po/shotwell-core/ar.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ar.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ar.po # Arabic Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -182,7 +182,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "" #: src/Resources.vala:130 @@ -3774,7 +3774,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/ast.po shotwell-0.11.92/po/shotwell-core/ast.po --- shotwell-0.11.91/po/shotwell-core/ast.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ast.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ast.po # Asturian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,8 +185,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3639,7 +3639,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/bg.po shotwell-0.11.92/po/shotwell-core/bg.po --- shotwell-0.11.91/po/shotwell-core/bg.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/bg.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/bg.po # Bulgarian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,8 +185,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Авторски права 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Авторски права 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3632,7 +3632,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/bn.po shotwell-0.11.92/po/shotwell-core/bn.po --- shotwell-0.11.91/po/shotwell-core/bn.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/bn.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/bn.po # Bengali Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -182,7 +182,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "" #: src/Resources.vala:130 @@ -3558,7 +3558,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/ca.po shotwell-0.11.92/po/shotwell-core/ca.po --- shotwell-0.11.91/po/shotwell-core/ca.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ca.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ca.po # Catalan Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -188,8 +188,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3762,8 +3762,8 @@ msgstr "Transicions principals de la projecció de diapositives" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Fundació Yorba" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Fundació Yorba" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/cs.po shotwell-0.11.92/po/shotwell-core/cs.po --- shotwell-0.11.91/po/shotwell-core/cs.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/cs.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/cs.po # Czech Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -188,8 +188,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3763,8 +3763,8 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/da.po shotwell-0.11.92/po/shotwell-core/da.po --- shotwell-0.11.91/po/shotwell-core/da.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/da.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/da.po # Danish Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -188,8 +188,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Ophavsret 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Ophavsret 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3706,8 +3706,8 @@ msgstr "Kerneovergange i diasshow" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/de.po shotwell-0.11.92/po/shotwell-core/de.po --- shotwell-0.11.91/po/shotwell-core/de.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/de.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/de.po # German Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1104,8 +1104,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3902,8 +3902,8 @@ msgstr "Standard Diaschau-Übergänge" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/el.po shotwell-0.11.92/po/shotwell-core/el.po --- shotwell-0.11.91/po/shotwell-core/el.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/el.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/el.po # Greek Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1101,8 +1101,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Πνευματικά δικαιώματα 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Πνευματικά δικαιώματα 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3926,8 +3926,8 @@ msgstr "Κεντρικές Μεταβάσεις Προβολής Διαφανειών" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/en_GB.po shotwell-0.11.92/po/shotwell-core/en_GB.po --- shotwell-0.11.91/po/shotwell-core/en_GB.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/en_GB.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/en_GB.po # English (Great Britain & Northern Ireland) Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1086,8 +1086,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3836,8 +3836,8 @@ msgstr "Core Slideshow Transitions" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/es.po shotwell-0.11.92/po/shotwell-core/es.po --- shotwell-0.11.91/po/shotwell-core/es.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/es.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/es.po # Spanish Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1095,8 +1095,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3874,8 +3874,8 @@ msgstr "Transiciones de Slideshow" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 La Fundación Yorba" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 La Fundación Yorba" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/et.po shotwell-0.11.92/po/shotwell-core/et.po --- shotwell-0.11.91/po/shotwell-core/et.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/et.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/et.po # Estonian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1087,8 +1087,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3837,8 +3837,8 @@ msgstr "Slaidiesitluse peamised üleminekud" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/eu.po shotwell-0.11.92/po/shotwell-core/eu.po --- shotwell-0.11.91/po/shotwell-core/eu.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/eu.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/eu.po # Basque Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1089,8 +1089,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3876,8 +3876,8 @@ msgstr "Oinarrizko diapositiba-trantsizioak" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/fi.po shotwell-0.11.92/po/shotwell-core/fi.po --- shotwell-0.11.91/po/shotwell-core/fi.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/fi.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/fi.po # Finnish Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -188,8 +188,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Tekijänoikeus 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Tekijänoikeus 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3679,7 +3679,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" "Tekijänoikeus 2010 Maxim Kartashev, Tekijänoikeus 2011 Yorba Foundation" diff -Nru shotwell-0.11.91/po/shotwell-core/fr.po shotwell-0.11.92/po/shotwell-core/fr.po --- shotwell-0.11.91/po/shotwell-core/fr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/fr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/fr.po # French Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1101,8 +1101,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3915,8 +3915,8 @@ msgstr "Transitions de diaporama principales" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/gl.po shotwell-0.11.92/po/shotwell-core/gl.po --- shotwell-0.11.91/po/shotwell-core/gl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/gl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/gl.po # Galician Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -188,8 +188,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Dereitos de autor 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Dereitos de autor 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3722,7 +3722,7 @@ msgstr "Núcleo de transicións de diaporama" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" "Dereitos de autor 2010 Maxim Kartashev, Dereitos de autor 2011 Yorba " "Foundation" diff -Nru shotwell-0.11.91/po/shotwell-core/he.po shotwell-0.11.92/po/shotwell-core/he.po --- shotwell-0.11.91/po/shotwell-core/he.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/he.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/he.po # Hebrew Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1080,7 +1080,7 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "כל הזכויות שמורות 2009—2010 קרן Yorba" #: src/Resources.vala:133 @@ -3821,7 +3821,7 @@ msgstr "מעברי ליבה של מצגות" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" "כל הזכויות שמורות 2010 Maxim Kartashev, כל הזכויות שמורות 2011 Yorba " "Foundation" diff -Nru shotwell-0.11.91/po/shotwell-core/hr.po shotwell-0.11.92/po/shotwell-core/hr.po --- shotwell-0.11.91/po/shotwell-core/hr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/hr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/hr.po # Croatian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,7 +185,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Prava 2009-2010 Yorba fundacija" #: src/Resources.vala:130 @@ -3758,8 +3758,8 @@ msgstr "Core prezentacijski prijelazi" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba fundacija" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba fundacija" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/hu.po shotwell-0.11.92/po/shotwell-core/hu.po --- shotwell-0.11.91/po/shotwell-core/hu.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/hu.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/hu.po # Hungarian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -191,8 +191,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3698,8 +3698,8 @@ msgstr "Alap diaátmenetek" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/id.po shotwell-0.11.92/po/shotwell-core/id.po --- shotwell-0.11.91/po/shotwell-core/id.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/id.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/id.po # Indonesian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,7 +185,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Hak cipta 2009-2010 Yayasan Yorba" #: src/Resources.vala:130 @@ -3575,7 +3575,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/it.po shotwell-0.11.92/po/shotwell-core/it.po --- shotwell-0.11.91/po/shotwell-core/it.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/it.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/it.po # Italian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1096,8 +1096,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3873,8 +3873,8 @@ msgstr "Transizioni diapositive di base" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/ja.po shotwell-0.11.92/po/shotwell-core/ja.po --- shotwell-0.11.91/po/shotwell-core/ja.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ja.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ja.po # Japanese Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1077,8 +1077,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3731,8 +3731,8 @@ msgstr "メインのスライドショーのトランジション" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/kk.po shotwell-0.11.92/po/shotwell-core/kk.po --- shotwell-0.11.91/po/shotwell-core/kk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/kk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/kk.po # Kazakh Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,8 +185,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3618,8 +3618,8 @@ msgstr "Слайдшоу арасында өту аралығы" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/ko.po shotwell-0.11.92/po/shotwell-core/ko.po --- shotwell-0.11.91/po/shotwell-core/ko.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ko.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ko.po # Korean Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1073,8 +1073,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3720,8 +3720,8 @@ msgstr "핵심 슬라이드 쇼 전환 효과 잼-전이: EOF " #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/lt.po shotwell-0.11.92/po/shotwell-core/lt.po --- shotwell-0.11.91/po/shotwell-core/lt.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/lt.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/lt.po # Lithuanian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -187,8 +187,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "© 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "© 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3699,7 +3699,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/lv.po shotwell-0.11.92/po/shotwell-core/lv.po --- shotwell-0.11.91/po/shotwell-core/lv.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/lv.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/lv.po # Latvian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1091,8 +1091,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Autortiesības 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Autortiesības 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3910,7 +3910,7 @@ msgstr "Pamata slīdrādes pārejas" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" "Autortiesības 2010 Maxim Kartashev, autortiesības 2011 Yorba Foundation" diff -Nru shotwell-0.11.91/po/shotwell-core/mk.po shotwell-0.11.92/po/shotwell-core/mk.po --- shotwell-0.11.91/po/shotwell-core/mk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/mk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/mk.po # Macedonian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -184,7 +184,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Авторско право 2009-2010 Yorba Фондација" #: src/Resources.vala:130 @@ -3719,7 +3719,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/nb.po shotwell-0.11.92/po/shotwell-core/nb.po --- shotwell-0.11.91/po/shotwell-core/nb.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/nb.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/nb.po # Norwegian Bokmal Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1088,8 +1088,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3847,8 +3847,8 @@ msgstr "Hovedoverganger for lysbildefremviser" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/nl.po shotwell-0.11.92/po/shotwell-core/nl.po --- shotwell-0.11.91/po/shotwell-core/nl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/nl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/nl.po # Dutch Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1096,8 +1096,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3878,8 +3878,8 @@ msgstr "Core-diavoorstellingsovergangen" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/pa.po shotwell-0.11.92/po/shotwell-core/pa.po --- shotwell-0.11.91/po/shotwell-core/pa.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/pa.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/pa.po # Panjabi (or Punjabi) Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -182,8 +182,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3572,7 +3572,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/pl.po shotwell-0.11.92/po/shotwell-core/pl.po --- shotwell-0.11.91/po/shotwell-core/pl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/pl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/pl.po # Polish Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1097,8 +1097,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Fundacja Yorba" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Fundacja Yorba" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3969,8 +3969,8 @@ msgstr "Główne przejścia pokazu slajdów" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Fundacja Yorba" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Fundacja Yorba" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/pt_BR.po shotwell-0.11.92/po/shotwell-core/pt_BR.po --- shotwell-0.11.91/po/shotwell-core/pt_BR.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/pt_BR.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/pt_BR.po # Portuguese (Brazil) Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1098,7 +1098,7 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Copyright 2009-2010 Fundação Yorba" #: src/Resources.vala:133 @@ -3881,8 +3881,8 @@ msgstr "Transições principais de exibição de slides" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Fundação Yorba" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Fundação Yorba" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/pt.po shotwell-0.11.92/po/shotwell-core/pt.po --- shotwell-0.11.91/po/shotwell-core/pt.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/pt.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/pt.po # Portuguese Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1095,8 +1095,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Direitos de autor 2009-2011 Fundação Yorba" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Direitos de autor 2009-2012 Fundação Yorba" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3858,7 +3858,7 @@ msgstr "Transições principais" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" "Direitos de autor 2010 Maxim Kartashev, Direitos de autor 2011 Fundação " "Yorba" diff -Nru shotwell-0.11.91/po/shotwell-core/ro.po shotwell-0.11.92/po/shotwell-core/ro.po --- shotwell-0.11.91/po/shotwell-core/ro.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ro.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ro.po # Romanian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1100,8 +1100,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3983,8 +3983,8 @@ msgstr "Tranziție principală pentru prezentare diapozitive " #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/ru.po shotwell-0.11.92/po/shotwell-core/ru.po --- shotwell-0.11.91/po/shotwell-core/ru.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ru.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ru.po # Russian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1098,8 +1098,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Авторские права 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Авторские права 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3960,7 +3960,7 @@ msgstr "Основные эффекты переходов" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "Авторские права 2010 Максим Карташев, 2011 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/shotwell.pot shotwell-0.11.92/po/shotwell-core/shotwell.pot --- shotwell-0.11.91/po/shotwell-core/shotwell.pot 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/shotwell.pot 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/shotwell.pot # PO message string template file for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1061,7 +1061,7 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "" #: src/Resources.vala:133 @@ -3709,7 +3709,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/sk.po shotwell-0.11.92/po/shotwell-core/sk.po --- shotwell-0.11.91/po/shotwell-core/sk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/sk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/sk.po # Slovak Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,7 +185,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Autorské práva 2009-2010 Nadácia Yorba" #: src/Resources.vala:130 @@ -3710,7 +3710,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/sl.po shotwell-0.11.92/po/shotwell-core/sl.po --- shotwell-0.11.91/po/shotwell-core/sl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/sl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/sl.po # Slovenian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1153,8 +1153,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Avtorske pravice 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Avtorske pravice 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3953,7 +3953,7 @@ msgstr "Osnovni prehodi predstavitev" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "Avtorske pravice © 2010 Maxim Kartashev, Avtorske pravice 2011 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/sr.po shotwell-0.11.92/po/shotwell-core/sr.po --- shotwell-0.11.91/po/shotwell-core/sr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/sr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/sr.po # Serbian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1099,7 +1099,7 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Сва права задржана © 2009 Yorba фондација" #: src/Resources.vala:133 @@ -3949,7 +3949,7 @@ msgstr "Основни прелаз покретног приказа" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" "Ауторска права 2010 Максим Карташев, Ауторска права 2011 Yorba Фондација" diff -Nru shotwell-0.11.91/po/shotwell-core/sv.po shotwell-0.11.92/po/shotwell-core/sv.po --- shotwell-0.11.91/po/shotwell-core/sv.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/sv.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/sv.po # Swedish Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1091,8 +1091,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Copyright 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3860,8 +3860,8 @@ msgstr "Standardövergångar för bildspel" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" -msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" +msgstr "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 msgid "Slide" diff -Nru shotwell-0.11.91/po/shotwell-core/ta.po shotwell-0.11.92/po/shotwell-core/ta.po --- shotwell-0.11.91/po/shotwell-core/ta.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/ta.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/ta.po # Tamil Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -185,7 +185,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "" #: src/Resources.vala:130 @@ -3561,7 +3561,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/te.po shotwell-0.11.92/po/shotwell-core/te.po --- shotwell-0.11.91/po/shotwell-core/te.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/te.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/te.po # Telugu Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1089,7 +1089,7 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "నకలుహక్కు 2009-2010 యోర్బ ఫౌండేషన్" #: src/Resources.vala:133 @@ -3837,7 +3837,7 @@ msgstr "స్లైడ్ ప్రదర్శన మారు మూల విధములు" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "నకలుహక్కులు 2010 మాక్జిమ్ కార్టషెవ్, నకలుహక్కులు 2011 యోర్బా ఫౌండేషన్" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/th.po shotwell-0.11.92/po/shotwell-core/th.po --- shotwell-0.11.91/po/shotwell-core/th.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/th.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/th.po # Thai Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -187,8 +187,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "สงวนลิขสิทธิ์ 2009-2011 โดย Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "สงวนลิขสิทธิ์ 2009-2012 โดย Yorba Foundation" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3575,7 +3575,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "สงวนลิขสิทธิ์ 2010 Maxim Kartashev, สงวนลิขสิทธิ์ 2011 มูลนิธิ Yorba" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/tr.po shotwell-0.11.92/po/shotwell-core/tr.po --- shotwell-0.11.91/po/shotwell-core/tr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/tr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/tr.po # Turkish Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -187,7 +187,7 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "Telif Hakkı 2009-2010 Yorba Vakfı" #: src/Resources.vala:130 @@ -3568,7 +3568,7 @@ msgstr "" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/uk.po shotwell-0.11.92/po/shotwell-core/uk.po --- shotwell-0.11.91/po/shotwell-core/uk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/uk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/uk.po # Ukrainian Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1102,7 +1102,7 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" msgstr "© Yorba Foundation, 2009–2011" #: src/Resources.vala:133 @@ -4009,7 +4009,7 @@ msgstr "Основні переходи під час показу слайдів" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "© Maxim Kartashev, 2010, © Yorba Foundation, 2011" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/vi.po shotwell-0.11.92/po/shotwell-core/vi.po --- shotwell-0.11.91/po/shotwell-core/vi.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/vi.po 2012-02-20 20:47:27.000000000 +0000 @@ -4,7 +4,7 @@ # This file is distributed under the same license as the shotwell package. # Dương 'Yang' ヤン Hà Nguyễn https://launchpad.net/~cmpitg, 2010. # Lê Hoàng Phương https://launchpad.net/~herophuong93, 2010. -# Vu Do Quynh , 2010-2011. +# Vu Do Quynh , 2010-2012. # Nguyễn Thái Ngọc Duy , 2010. # msgid "" @@ -1087,8 +1087,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "Bản quyền 2009-2011 Yorba Foundation" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "Bản quyền 2009-2012 Yorba Foundation" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3780,7 +3780,7 @@ msgstr "Quá trình chuyển đổi ảnh chiếu chủ yếu" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "Bản quyền 2010 Maxim Kartashev, Bản quyền 2011 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/zh_CN.po shotwell-0.11.92/po/shotwell-core/zh_CN.po --- shotwell-0.11.91/po/shotwell-core/zh_CN.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/zh_CN.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/zh_CN.po # Chinese (Mainland China / PRC) Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -189,8 +189,8 @@ #: plugins/shotwell-publishing/PicasaPublishing.vala:32 #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "版权所有 2009-2011 Yorba 基金会" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "版权所有 2009-2012 Yorba 基金会" #: src/Resources.vala:130 msgid "Rotate _Right" @@ -3585,7 +3585,7 @@ msgstr "主要幻灯片变换" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "版权所有 2010 Maxim Kartashev,版权所有 2009-2010 Yorba Foundation" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-core/zh_TW.po shotwell-0.11.92/po/shotwell-core/zh_TW.po --- shotwell-0.11.91/po/shotwell-core/zh_TW.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-core/zh_TW.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-core/zh_TW.po # Chinese (Taiwan) Translation for Shotwell Core Components -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" @@ -1071,8 +1071,8 @@ #: plugins/shotwell-publishing/YouTubePublishing.vala:32 #: plugins/shotwell-publishing/FlickrPublishing.vala:32 #: plugins/shotwell-publishing/PicasaPublishing.vala:32 -msgid "Copyright 2009-2011 Yorba Foundation" -msgstr "著作權所有 2009-2011 Yorba 基金會" +msgid "Copyright 2009-2012 Yorba Foundation" +msgstr "著作權所有 2009-2012 Yorba 基金會" #: src/Resources.vala:133 msgid "Rotate _Right" @@ -3720,7 +3720,7 @@ msgstr "核心投影秀轉場" #: plugins/shotwell-transitions/shotwell-transitions.vala:68 -msgid "Copyright 2010 Maxim Kartashev, Copyright 2011 Yorba Foundation" +msgid "Copyright 2010 Maxim Kartashev, Copyright 2011-2012 Yorba Foundation" msgstr "版權所有 2010 Maxim Kartashev,版權所有 2011 Yorba 基金會" #: plugins/shotwell-transitions/SlideEffect.vala:20 diff -Nru shotwell-0.11.91/po/shotwell-extras/ar.po shotwell-0.11.92/po/shotwell-extras/ar.po --- shotwell-0.11.91/po/shotwell-extras/ar.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ar.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ar.po # Arabic Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ast.po shotwell-0.11.92/po/shotwell-extras/ast.po --- shotwell-0.11.91/po/shotwell-extras/ast.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ast.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ast.po # Asturian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/bg.po shotwell-0.11.92/po/shotwell-extras/bg.po --- shotwell-0.11.91/po/shotwell-extras/bg.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/bg.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/bg.po # Bulgarian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/bn.po shotwell-0.11.92/po/shotwell-extras/bn.po --- shotwell-0.11.91/po/shotwell-extras/bn.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/bn.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/bn.po # Bengali Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ca.po shotwell-0.11.92/po/shotwell-extras/ca.po --- shotwell-0.11.91/po/shotwell-extras/ca.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ca.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ca.po # Catalan Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/cs.po shotwell-0.11.92/po/shotwell-extras/cs.po --- shotwell-0.11.91/po/shotwell-extras/cs.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/cs.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/cs.po # Czech Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/da.po shotwell-0.11.92/po/shotwell-extras/da.po --- shotwell-0.11.91/po/shotwell-extras/da.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/da.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/da.po # Danish Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/de.po shotwell-0.11.92/po/shotwell-extras/de.po --- shotwell-0.11.91/po/shotwell-extras/de.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/de.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/de.po # German Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/el.po shotwell-0.11.92/po/shotwell-extras/el.po --- shotwell-0.11.91/po/shotwell-extras/el.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/el.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/el.po # Greek Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/en_GB.po shotwell-0.11.92/po/shotwell-extras/en_GB.po --- shotwell-0.11.91/po/shotwell-extras/en_GB.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/en_GB.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/en_GB.po # English (Great Britain & Northern Ireland) Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/es.po shotwell-0.11.92/po/shotwell-extras/es.po --- shotwell-0.11.91/po/shotwell-extras/es.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/es.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/es.po # Spanish Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/et.po shotwell-0.11.92/po/shotwell-extras/et.po --- shotwell-0.11.91/po/shotwell-extras/et.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/et.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/et.po # Estonian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/eu.po shotwell-0.11.92/po/shotwell-extras/eu.po --- shotwell-0.11.91/po/shotwell-extras/eu.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/eu.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/eu.po # Basque Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/fi.po shotwell-0.11.92/po/shotwell-extras/fi.po --- shotwell-0.11.91/po/shotwell-extras/fi.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/fi.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/fi.po # Finnish Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/fr.po shotwell-0.11.92/po/shotwell-extras/fr.po --- shotwell-0.11.91/po/shotwell-extras/fr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/fr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/fr.po # French Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/gl.po shotwell-0.11.92/po/shotwell-extras/gl.po --- shotwell-0.11.91/po/shotwell-extras/gl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/gl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/gl.po # Galician Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/he.po shotwell-0.11.92/po/shotwell-extras/he.po --- shotwell-0.11.91/po/shotwell-extras/he.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/he.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/he.po # Hebrew Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/hr.po shotwell-0.11.92/po/shotwell-extras/hr.po --- shotwell-0.11.91/po/shotwell-extras/hr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/hr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/hr.po # Croatian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/hu.po shotwell-0.11.92/po/shotwell-extras/hu.po --- shotwell-0.11.91/po/shotwell-extras/hu.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/hu.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/hu.po # Hungarian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/id.po shotwell-0.11.92/po/shotwell-extras/id.po --- shotwell-0.11.91/po/shotwell-extras/id.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/id.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/id.po # Indonesian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/it.po shotwell-0.11.92/po/shotwell-extras/it.po --- shotwell-0.11.91/po/shotwell-extras/it.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/it.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/it.po # Italian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ja.po shotwell-0.11.92/po/shotwell-extras/ja.po --- shotwell-0.11.91/po/shotwell-extras/ja.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ja.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ja.po # Japanese Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/kk.po shotwell-0.11.92/po/shotwell-extras/kk.po --- shotwell-0.11.91/po/shotwell-extras/kk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/kk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/kk.po # Kazakh Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ko.po shotwell-0.11.92/po/shotwell-extras/ko.po --- shotwell-0.11.91/po/shotwell-extras/ko.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ko.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ko.po # Korean Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/lt.po shotwell-0.11.92/po/shotwell-extras/lt.po --- shotwell-0.11.91/po/shotwell-extras/lt.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/lt.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/lt.po # Lithuanian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/lv.po shotwell-0.11.92/po/shotwell-extras/lv.po --- shotwell-0.11.91/po/shotwell-extras/lv.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/lv.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/lv.po # Latvian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/mk.po shotwell-0.11.92/po/shotwell-extras/mk.po --- shotwell-0.11.91/po/shotwell-extras/mk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/mk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/mk.po # Macedonian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/nb.po shotwell-0.11.92/po/shotwell-extras/nb.po --- shotwell-0.11.91/po/shotwell-extras/nb.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/nb.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/nb.po # Norwegian Bokmal Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/nl.po shotwell-0.11.92/po/shotwell-extras/nl.po --- shotwell-0.11.91/po/shotwell-extras/nl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/nl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/nl.po # Dutch Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/pa.po shotwell-0.11.92/po/shotwell-extras/pa.po --- shotwell-0.11.91/po/shotwell-extras/pa.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/pa.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/pa.po # Panjabi (Punjabi) Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/pl.po shotwell-0.11.92/po/shotwell-extras/pl.po --- shotwell-0.11.91/po/shotwell-extras/pl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/pl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/pl.po # Polish Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/pt_BR.po shotwell-0.11.92/po/shotwell-extras/pt_BR.po --- shotwell-0.11.91/po/shotwell-extras/pt_BR.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/pt_BR.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/pt_BR.po # Portuguese (Brazil) Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/pt.po shotwell-0.11.92/po/shotwell-extras/pt.po --- shotwell-0.11.91/po/shotwell-extras/pt.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/pt.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/pt.po # Portuguese Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ro.po shotwell-0.11.92/po/shotwell-extras/ro.po --- shotwell-0.11.91/po/shotwell-extras/ro.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ro.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ro.po # Romanian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ru.po shotwell-0.11.92/po/shotwell-extras/ru.po --- shotwell-0.11.91/po/shotwell-extras/ru.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ru.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ru.po # Russian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/shotwell-extras.pot shotwell-0.11.92/po/shotwell-extras/shotwell-extras.pot --- shotwell-0.11.91/po/shotwell-extras/shotwell-extras.pot 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/shotwell-extras.pot 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/shotwell-extras.pot # PO message string template file for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/sk.po shotwell-0.11.92/po/shotwell-extras/sk.po --- shotwell-0.11.91/po/shotwell-extras/sk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/sk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/sk.po # Slovak Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/sl.po shotwell-0.11.92/po/shotwell-extras/sl.po --- shotwell-0.11.91/po/shotwell-extras/sl.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/sl.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/sl.po # Slovenian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/sr.po shotwell-0.11.92/po/shotwell-extras/sr.po --- shotwell-0.11.91/po/shotwell-extras/sr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/sr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/sr.po # Serbian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/sv.po shotwell-0.11.92/po/shotwell-extras/sv.po --- shotwell-0.11.91/po/shotwell-extras/sv.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/sv.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/sv.po # Swedish Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/ta.po shotwell-0.11.92/po/shotwell-extras/ta.po --- shotwell-0.11.91/po/shotwell-extras/ta.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/ta.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/ta.po # Tamil Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/te.po shotwell-0.11.92/po/shotwell-extras/te.po --- shotwell-0.11.91/po/shotwell-extras/te.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/te.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/te.po # Telugu Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/th.po shotwell-0.11.92/po/shotwell-extras/th.po --- shotwell-0.11.91/po/shotwell-extras/th.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/th.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/th.po # Thai Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/tr.po shotwell-0.11.92/po/shotwell-extras/tr.po --- shotwell-0.11.91/po/shotwell-extras/tr.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/tr.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/tr.po # Turkish Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/uk.po shotwell-0.11.92/po/shotwell-extras/uk.po --- shotwell-0.11.91/po/shotwell-extras/uk.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/uk.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/uk.po # Ukrainian Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/zh_CN.po shotwell-0.11.92/po/shotwell-extras/zh_CN.po --- shotwell-0.11.91/po/shotwell-extras/zh_CN.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/zh_CN.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/zh_CN.po # Chinese (Mainland China / PRC) Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/po/shotwell-extras/zh_TW.po shotwell-0.11.92/po/shotwell-extras/zh_TW.po --- shotwell-0.11.91/po/shotwell-extras/zh_TW.po 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/po/shotwell-extras/zh_TW.po 2012-02-20 20:47:27.000000000 +0000 @@ -1,6 +1,6 @@ # po/shotwell-extras/zh_TW.po # Chinese (Taiwan) Translation for Shotwell Extra Plugins -# Copyright (C) 2009-2011 Yorba Foundation +# Copyright (C) 2009-2012 Yorba Foundation # This file is distributed under the GNU LGPL, version 2.1. # msgid "" diff -Nru shotwell-0.11.91/README shotwell-0.11.92/README --- shotwell-0.11.91/README 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/README 2012-02-20 20:47:27.000000000 +0000 @@ -57,5 +57,5 @@ - Copyright 2009-2011 Yorba Foundation + Copyright 2009-2012 Yorba Foundation diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseDriver.vala shotwell-0.11.92/src/alien_db/AlienDatabaseDriver.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseDriver.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseDriver.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * A simple class to represent an alien database driver ID. - */ -public class AlienDatabaseDriverID { - public string id; - - public AlienDatabaseDriverID(string id) { - this.id = id; - } - - public static uint hash(void *a) { - return ((AlienDatabaseDriverID *) a)->id.hash(); - } - - public static bool equal(void *a, void *b) { - return ((AlienDatabaseDriverID *) a)->id == ((AlienDatabaseDriverID *) b)->id; - } -} - -/** - * The main driver interface that all plugins should implement. This driver - * interface is designed to automatically discover databases and create - * instances of AlienDatabase that can interrogate the data. - */ -public interface AlienDatabaseDriver : Object { - /** - * Return a unique ID for this alien database driver. - */ - public abstract AlienDatabaseDriverID get_id(); - - /** - * Return the display name for this driver. - */ - public abstract string get_display_name(); - - /** - * This method returns all databases that are automatically discovered by - * the driver. - */ - public abstract Gee.Collection get_discovered_databases(); - - /** - * This method opens a database given a database ID and returns an object - * that is able to interrogate the data contained in the database. - */ - public abstract AlienDatabase open_database(AlienDatabaseID db_id) throws DatabaseError, AlienDatabaseError; - - /** - * This method opens a database given a file and returns an object - * that is able to interrogate the data contained in the database. - */ - public abstract AlienDatabase open_database_from_file(File db_file) throws DatabaseError, AlienDatabaseError; - - public abstract string get_menu_name(); - - public abstract Gtk.ActionEntry get_action_entry(); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseEvent.vala shotwell-0.11.92/src/alien_db/AlienDatabaseEvent.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseEvent.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseEvent.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * The main interface for a single instance of an event held in the database. - */ -public interface AlienDatabaseEvent : Object { - public abstract string get_name(); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseHandler.vala shotwell-0.11.92/src/alien_db/AlienDatabaseHandler.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseHandler.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseHandler.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * The core handler that is responsible for handling the different plugins - * and dispatching requests to the relevant driver. - */ -public class AlienDatabaseHandler { - private static AlienDatabaseHandler instance; - private Gee.Map driver_map; - - /** - * Initialisation method that creates a singleton instance. - */ - public static void init() { - // Check for null in case init() is called more than once. - if(instance == null) - instance = new AlienDatabaseHandler(); - } - - /** - * Termination method that clears the singleton instance. - */ - public static void terminate() { - instance = null; - } - - public static AlienDatabaseHandler get_instance() { - return instance; - } - - private AlienDatabaseHandler() { - driver_map = new Gee.HashMap( - AlienDatabaseDriverID.hash, AlienDatabaseDriverID.equal, AlienDatabaseDriverID.equal - ); - } - - public void register_driver(AlienDatabaseDriver driver) { - driver_map.set(driver.get_id(), driver); - } - - public void unregister_driver(AlienDatabaseDriver driver) { - driver_map.unset(driver.get_id()); - } - - public Gee.Collection get_drivers() { - return driver_map.values; - } - - public AlienDatabaseDriver get_driver(AlienDatabaseDriverID driver_id) { - AlienDatabaseDriver driver = driver_map.get(driver_id); - if (driver == null) - warning("Could not find driver for id: %s", driver_id.id); - return driver; - } - - public Gee.Collection get_discovered_databases() { - Gee.ArrayList discovered_databases = - new Gee.ArrayList(); - foreach (AlienDatabaseDriver driver in driver_map.values) { - discovered_databases.add_all(driver.get_discovered_databases()); - } - return discovered_databases; - } - - public void add_menu_entries(Gtk.UIManager ui, string placeholder) { - foreach (AlienDatabaseDriver driver in get_drivers()) { - ui.add_ui(ui.new_merge_id(), placeholder, - driver.get_menu_name(), - driver.get_action_entry().name, - Gtk.UIManagerItemType.MENUITEM, false); - } - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseImportDialogController.vala shotwell-0.11.92/src/alien_db/AlienDatabaseImportDialogController.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseImportDialogController.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseImportDialogController.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -public class AlienDatabaseImportDialogController { - private AlienDatabaseImportDialog dialog; - - public AlienDatabaseImportDialogController(string title, AlienDatabaseDriver driver, - BatchImport.ImportReporter? reporter = null) { - if (reporter == null) - reporter = alien_import_reporter; - - Gtk.Builder builder = AppWindow.create_builder(); - dialog = builder.get_object("alien-db-import_dialog") as AlienDatabaseImportDialog; - dialog.set_builder(builder); - dialog.setup(title, driver, reporter); - } - - public void execute() { - dialog.execute(); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseImportDialog.vala shotwell-0.11.92/src/alien_db/AlienDatabaseImportDialog.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseImportDialog.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseImportDialog.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,223 +0,0 @@ -/* Copyright 2009-2011 Yorba Foundation - * - * This software is licensed under the GNU LGPL (version 2.1 or later). - * See the COPYING file in this distribution. - */ - -namespace AlienDb { - -public class AlienDatabaseImportDialog : Gtk.Dialog { - private static const int MSG_NOTEBOOK_PAGE_EMPTY = 0; - private static const int MSG_NOTEBOOK_PAGE_PROGRESS = 1; - private static const int MSG_NOTEBOOK_PAGE_ERROR = 2; - - private Gtk.Builder builder; - - private AlienDatabaseDriver driver; - private DiscoveredAlienDatabase? selected_database = null; - private File? selected_file = null; - private Gtk.FileChooserButton file_chooser; - private Gtk.RadioButton? file_chooser_radio; - private Gtk.Notebook message_notebook; - private Gtk.ProgressBar prepare_progress_bar; - private Gtk.Label error_message_label; - private unowned BatchImport.ImportReporter reporter; - - public void set_builder(Gtk.Builder builder) { - this.builder = builder; - } - - public void setup(string title, AlienDatabaseDriver driver, - BatchImport.ImportReporter reporter) { - set_title(title); - set_parent_window(AppWindow.get_instance().get_parent_window()); - set_transient_for(AppWindow.get_instance()); - this.driver = driver; - this.reporter = reporter; - - file_chooser = builder.get_object("db_filechooserbutton") as Gtk.FileChooserButton; - message_notebook = builder.get_object("message_notebook") as Gtk.Notebook; - message_notebook.set_current_page(MSG_NOTEBOOK_PAGE_EMPTY); - prepare_progress_bar = builder.get_object("prepare_progress_bar") as Gtk.ProgressBar; - error_message_label = builder.get_object("import_error_label") as Gtk.Label; - - Gtk.Box options_box = builder.get_object("options_box") as Gtk.Box; - - Gee.Collection discovered_databases = driver.get_discovered_databases(); - if (discovered_databases.size > 0) { - Gtk.RadioButton db_radio = null; - foreach (DiscoveredAlienDatabase db in discovered_databases) { - string db_radio_label = - _("Import from default %1$s library (%2$s)").printf( - driver.get_display_name(), - collapse_user_path(db.get_id().driver_specific_uri) - ); - db_radio = create_radio_button(options_box, db_radio, db, db_radio_label); - } - file_chooser_radio = create_radio_button( - options_box, db_radio, null, - _("Import from another %s database file:").printf(driver.get_display_name()) - ); - } else { - Gtk.Label custom_file_label = new Gtk.Label( - _("Import from a %s database file:").printf(driver.get_display_name()) - ); - options_box.pack_start(custom_file_label, true, true, 6); - } - set_ok_sensitivity(); - } - - public void execute() { - show_all(); - - bool is_finished = false; - while (!is_finished) { - if (run() == Gtk.ResponseType.OK) - is_finished = execute_import(); - else - is_finished = true; - } - - destroy(); - } - - // - // The bit that does all the work once the OK button has been clicked. - // - private bool execute_import() { - bool result = false; - AlienDatabase? alien_db = null; - try { - if (selected_database != null) - alien_db = selected_database.get_database(); - else if (selected_file != null) - alien_db = driver.open_database_from_file(selected_file); - if (alien_db == null) { - message_notebook.set_current_page(MSG_NOTEBOOK_PAGE_ERROR); - error_message_label.set_label(_("No database selected")); - } else { - message_notebook.set_current_page(MSG_NOTEBOOK_PAGE_PROGRESS); - prepare_progress_bar.set_fraction(0.0); - set_response_sensitive(Gtk.ResponseType.OK, false); - set_response_sensitive(Gtk.ResponseType.CANCEL, false); - spin_event_loop(); - - SortedList jobs = - new SortedList(import_job_comparator); - Gee.ArrayList already_imported = - new Gee.ArrayList(); - Gee.ArrayList failed = - new Gee.ArrayList(); - - Gee.Collection photos = alien_db.get_photos(); - int photo_total = photos.size; - int photo_idx = 0; - foreach (AlienDatabasePhoto src_photo in photos) { - AlienDatabaseImportSource import_source = new AlienDatabaseImportSource(src_photo); - - if (import_source.is_already_imported()) { - message("Skipping import of %s: checksum detected in library", - import_source.get_filename()); - already_imported.add(new AlienDatabaseImportJob(import_source)); - - continue; - } - - jobs.add(new AlienDatabaseImportJob(import_source)); - photo_idx++; - prepare_progress_bar.set_fraction((double)photo_idx / (double)photo_total); - spin_event_loop(); - } - - // Go through the motions of importing even if the job size is - // zero so that the reported function can display a message dialog - // notifying the user that nothing was imported - string db_name = _("%s Database").printf(alien_db.get_display_name()); - BatchImport batch_import = new BatchImport(jobs, db_name, reporter, failed, - already_imported); - - LibraryWindow.get_app().enqueue_batch_import(batch_import, true); - // However, if there is really nothing to import, don't switch - // to the import queue page so that the user is not faced with - // an empty page - if (jobs.size > 0) - LibraryWindow.get_app().switch_to_import_queue_page(); - // clean up - if (selected_database != null) { - selected_database.release_database(); - selected_database = null; - } - - result = true; - } - } catch (Error e) { - message_notebook.set_current_page(MSG_NOTEBOOK_PAGE_ERROR); - error_message_label.set_label(_("Shotwell failed to load the database file")); - // most failures should happen before the two buttons have been set - // to the insensitive state but you never know so set them back to the - // normal state so that the user can interact with them - set_response_sensitive(Gtk.ResponseType.OK, true); - set_response_sensitive(Gtk.ResponseType.CANCEL, true); - } - return result; - } - - // - // Signals - // - public void on_file_chooser_file_set() { - selected_file = file_chooser.get_file(); - if (file_chooser_radio != null) - file_chooser_radio.active = true; - set_ok_sensitivity(); - } - - // - // Private methods - // - private void set_ok_sensitivity() { - set_response_sensitive(Gtk.ResponseType.OK, (selected_database != null || selected_file != null)); - } - - private Gtk.RadioButton create_radio_button( - Gtk.Box box, Gtk.RadioButton? group, DiscoveredAlienDatabase? alien_db, string label - ) { - var button = new Gtk.RadioButton.with_label_from_widget (group, label); - if (group == null) { // first radio button is active - button.active = true; - selected_database = alien_db; - } - button.toggled.connect (() => { - if (button.active) { - this.selected_database = alien_db; - set_ok_sensitivity(); - } - }); - box.pack_start(button, true, true, 6); - return button; - } - - private string collapse_user_path(string path) { - string result = path; - string home_dir = Environment.get_home_dir(); - if (path.has_prefix(home_dir)) { - long cidx = home_dir.length; - if (home_dir[home_dir.length - 1] == '/') - cidx--; - result = "~%s".printf(path.substring(cidx)); - } - return result; - } - - private int64 import_job_comparator(void *a, void *b) { - return ((AlienDatabaseImportJob *) a)->get_exposure_time() - - ((AlienDatabaseImportJob *) b)->get_exposure_time(); - } -} - -private void alien_import_reporter(ImportManifest manifest, BatchImportRoll import_roll) { - ImportUI.report_manifest(manifest, true); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseImportJob.vala shotwell-0.11.92/src/alien_db/AlienDatabaseImportJob.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseImportJob.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseImportJob.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,169 +0,0 @@ -/* Copyright 2009-2011 Yorba Foundation - * - * This software is licensed under the GNU LGPL (version 2.1 or later). - * See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * A specialized import job implementation for alien databases. - */ -public class AlienDatabaseImportJob : BatchImportJob { - private AlienDatabaseImportSource import_source; - private File? src_file; - private uint64 filesize; - private time_t exposure_time; - private AlienDatabaseImportJob? associated = null; - private HierarchicalTagIndex? detected_htags = null; - - public AlienDatabaseImportJob(AlienDatabaseImportSource import_source) { - this.import_source = import_source; - - // stash everything called in prepare(), as it may/will be called from a separate thread - src_file = import_source.get_file(); - filesize = import_source.get_filesize(); - exposure_time = import_source.get_exposure_time(); - } - - private HierarchicalTagIndex? build_exclusion_index(Gee.Collection src_tags) { - Gee.Set detected_htags = new Gee.HashSet(); - - foreach (AlienDatabaseTag src_tag in src_tags) { - string? prepped = HierarchicalTagUtilities.join_path_components( - Tag.prep_tag_names( - build_path_components(src_tag) - ) - ); - - if (prepped != null && prepped.has_prefix(Tag.PATH_SEPARATOR_STRING)) { - detected_htags.add(prepped); - - Gee.List parents = HierarchicalTagUtilities.enumerate_parent_paths(prepped); - foreach (string parent in parents) - detected_htags.add(parent); - } - } - - return (detected_htags.size > 0) ? HierarchicalTagIndex.from_paths(detected_htags) : null; - } - - public time_t get_exposure_time() { - return exposure_time; - } - - public override string get_dest_identifier() { - return import_source.get_filename(); - } - - public override string get_source_identifier() { - return import_source.get_filename(); - } - - public override bool is_directory() { - return false; - } - - public override string get_basename() { - return src_file.get_basename(); - } - - public override string get_path() { - return src_file.get_parent().get_path(); - } - - public override void set_associated(BatchImportJob associated) { - this.associated = associated as AlienDatabaseImportJob; - } - - public override bool determine_file_size(out uint64 filesize, out File file) { - file = null; - filesize = this.filesize; - - return true; - } - - public override bool prepare(out File file_to_import, out bool copy_to_library) throws Error { - file_to_import = src_file; - copy_to_library = false; - - detected_htags = build_exclusion_index(import_source.get_photo().get_tags()); - - return true; - } - - public override bool complete(MediaSource source, BatchImportRoll import_roll) throws Error { - LibraryPhoto? photo = source as LibraryPhoto; - if (photo == null) - return false; - - AlienDatabasePhoto src_photo = import_source.get_photo(); - - // tags - if (detected_htags != null) { - Gee.Collection paths = detected_htags.get_all_paths(); - - foreach (string path in paths) - Tag.for_path(path); - } - - Gee.Collection src_tags = src_photo.get_tags(); - foreach (AlienDatabaseTag src_tag in src_tags) { - string? prepped = HierarchicalTagUtilities.join_path_components( - Tag.prep_tag_names( - build_path_components(src_tag) - ) - ); - if (prepped != null) { - if (HierarchicalTagUtilities.enumerate_path_components(prepped).size == 1) { - if (prepped.has_prefix(Tag.PATH_SEPARATOR_STRING)) - prepped = HierarchicalTagUtilities.hierarchical_to_flat(prepped); - } else { - Gee.List parents = - HierarchicalTagUtilities.enumerate_parent_paths(prepped); - - assert(parents.size > 0); - - string top_level_parent = parents.get(0); - string flat_top_level_parent = - HierarchicalTagUtilities.hierarchical_to_flat(top_level_parent); - - if (Tag.global.exists(flat_top_level_parent)) - Tag.for_path(flat_top_level_parent).promote(); - } - - Tag.for_path(prepped).attach(photo); - } - } - // event - AlienDatabaseEvent? src_event = src_photo.get_event(); - if (src_event != null) { - string? prepped = prepare_input_text(src_event.get_name(), - PrepareInputTextOptions.DEFAULT, -1); - if (prepped != null) - Event.generate_single_event(photo, import_roll.generated_events, prepped); - } - // rating - photo.set_rating(src_photo.get_rating()); - // title - string? title = src_photo.get_title(); - if (title != null) - photo.set_title(title); - // import ID - photo.set_import_id(import_roll.import_id); - - return true; - } - - private string[] build_path_components(AlienDatabaseTag tag) { - // use a linked list as we are always inserting in head position - Gee.List components = new Gee.LinkedList(); - for (AlienDatabaseTag current_tag = tag; current_tag != null; current_tag = current_tag.get_parent()) { - components.insert(0, HierarchicalTagUtilities.make_flat_tag_safe(current_tag.get_name())); - } - return components.to_array(); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseImportSource.vala shotwell-0.11.92/src/alien_db/AlienDatabaseImportSource.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseImportSource.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseImportSource.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * Photo source implementation for alien databases. This class is responsible - * for extracting meta-data out of a source photo to support the import - * process. - * - * This class does not extend PhotoSource in order to minimise the API to the - * absolute minimum required to run the import job. - */ -public class AlienDatabaseImportSource { - private AlienDatabasePhoto db_photo; - private string? title = null; - private string? preview_md5 = null; - private uint64 file_size; - private time_t modification_time; - private MetadataDateTime? exposure_time; - - public AlienDatabaseImportSource(AlienDatabasePhoto db_photo) { - this.db_photo = db_photo; - File photo = File.new_for_path(db_photo.get_folder_path()). - get_child(db_photo.get_filename()); - - PhotoMetadata? metadata = new PhotoMetadata(); - try { - metadata.read_from_file(photo); - } catch(Error e) { - warning("Could not get file metadata for %s: %s", get_filename(), e.message); - metadata = null; - } - - title = (metadata != null) ? metadata.get_title() : null; - exposure_time = (metadata != null) ? metadata.get_exposure_date_time() : null; - PhotoPreview? preview = metadata != null ? metadata.get_preview(0) : null; - if (preview != null) { - try { - uint8[] preview_raw = preview.flatten(); - preview_md5 = md5_binary(preview_raw, preview_raw.length); - } catch(Error e) { - warning("Could not get raw preview for %s: %s", get_filename(), e.message); - } - } -#if TRACE_MD5 - debug("Photo MD5 %s: preview=%s", get_filename(), preview_md5); -#endif - - try { - file_size = query_total_file_size(photo); - } catch(Error e) { - warning("Could not get file size for %s: %s", get_filename(), e.message); - } - try { - modification_time = query_file_modified(photo); - } catch(Error e) { - warning("Could not get modification time for %s: %s", get_filename(), e.message); - } - } - - public string get_filename() { - return db_photo.get_filename(); - } - - public string get_fulldir() { - return db_photo.get_folder_path(); - } - - public File get_file() { - return File.new_for_path(get_fulldir()).get_child(get_filename()); - } - - public string get_name() { - return !is_string_empty(title) ? title : get_filename(); - } - - public string? get_title() { - return title; - } - - public PhotoFileFormat get_file_format() { - return PhotoFileFormat.get_by_basename_extension(get_filename()); - } - - public string to_string() { - return get_name(); - } - - public time_t get_exposure_time() { - return (exposure_time != null) ? exposure_time.get_timestamp() : modification_time; - } - - public uint64 get_filesize() { - return file_size; - } - - public AlienDatabasePhoto get_photo() { - return db_photo; - } - - public bool is_already_imported() { - // ignore trashed duplicates - return (preview_md5 != null) - ? LibraryPhoto.has_nontrash_duplicate(null, preview_md5, null, get_file_format()) - : false; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabasePhoto.vala shotwell-0.11.92/src/alien_db/AlienDatabasePhoto.vala --- shotwell-0.11.91/src/alien_db/AlienDatabasePhoto.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabasePhoto.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * The main interface for a single instance of a photo held in the database. - * This interface assumes that the photograph can be accessed via the Vala - * File classes. - */ -public interface AlienDatabasePhoto : Object { - public abstract string get_folder_path(); - - public abstract string get_filename(); - - public abstract Gee.Collection get_tags(); - - public abstract AlienDatabaseEvent? get_event(); - - public abstract Rating get_rating(); - - public abstract string? get_title(); - - public abstract ImportID? get_import_id(); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseTag.vala shotwell-0.11.92/src/alien_db/AlienDatabaseTag.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseTag.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseTag.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * The main interface for a single instance of a tag held in the database. - */ -public interface AlienDatabaseTag : Object { - public abstract string get_name(); - - public abstract AlienDatabaseTag? get_parent(); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabase.vala shotwell-0.11.92/src/alien_db/AlienDatabase.vala --- shotwell-0.11.91/src/alien_db/AlienDatabase.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabase.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* Copyright 2009-2011 Yorba Foundation - * - * This software is licensed under the GNU LGPL (version 2.1 or later). - * See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * The error domain for alien databases - */ -public errordomain AlienDatabaseError { - // Unsupported version: this can be due to an old legacy database, - // a new database version that this version of Shotwell doesn't support - // or a database version that could not be identified properly. - UNSUPPORTED_VERSION -} - -/** - * A simple struct to represent an alien database ID. - */ -public class AlienDatabaseID { - public AlienDatabaseDriverID driver_id; - public string driver_specific_uri; - - public AlienDatabaseID(AlienDatabaseDriverID driver_id, string driver_specific_uri) { - this.driver_id = driver_id; - this.driver_specific_uri = driver_specific_uri; - } - - public AlienDatabaseID.from_uri(string db_uri) { - string[] uri_elements = db_uri.split(":", 2); - if (uri_elements.length < 2) { - error("Cannot create alien database ID from URI: %s", db_uri); - } else { - this.driver_id = new AlienDatabaseDriverID(uri_elements[0]); - this.driver_specific_uri = uri_elements[1]; - } - } - - public string to_uri() { - return "%s:%s".printf(driver_id.id, driver_specific_uri); - } - - public static uint hash(void *a) { - return ( - AlienDatabaseDriverID.hash(&((AlienDatabaseID *) a)->driver_id) ^ - ((AlienDatabaseID *) a)->driver_specific_uri.hash() - ); - } - - public static bool equal(void *a, void *b) { - return ( - AlienDatabaseDriverID.equal(&((AlienDatabaseID *) a)->driver_id, &((AlienDatabaseID *) b)->driver_id) && - (((AlienDatabaseID *) a)->driver_specific_uri == ((AlienDatabaseID *) b)->driver_specific_uri) - ); - } -} - -/** - * The main database interface that all plugins should implement. The driver - * should return an instance of a class that implements this interface for - * each open database. This interface is then used to query the underlying - * database in order to import photographs. The driver itself is free to - * instantiate objects of different classes for different database files if - * required. For example, it is conceivable that a driver could supply - * different implementations for different versions of the same database. - */ -public interface AlienDatabase : Object { - public abstract string get_uri(); - - public abstract string get_display_name(); - - public abstract AlienDatabaseVersion get_version() throws DatabaseError; - - public abstract Gee.Collection get_photos() throws DatabaseError; -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDatabaseVersion.vala shotwell-0.11.92/src/alien_db/AlienDatabaseVersion.vala --- shotwell-0.11.91/src/alien_db/AlienDatabaseVersion.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDatabaseVersion.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * A class that represents a version in the form x.y.z and is able to compare - * different versions. - */ -public class AlienDatabaseVersion : Object, Gee.Comparable { - private int[] version; - - public AlienDatabaseVersion(int[] version) { - this.version = version; - } - - public AlienDatabaseVersion.from_string(string str_version, string separator = ".") { - string[] version_items = str_version.split(separator); - this.version = new int[version_items.length]; - for (int i = 0; i < version_items.length; i++) - this.version[i] = int.parse(version_items[i]); - } - - public string to_string() { - string[] version_items = new string[this.version.length]; - for (int i = 0; i < this.version.length; i++) - version_items[i] = this.version[i].to_string(); - return string.joinv(".", version_items); - } - - public int compare_to(AlienDatabaseVersion other) { - int max_len = ((this.version.length > other.version.length) ? - this.version.length : other.version.length); - int res = 0; - for(int i = 0; i < max_len; i++) { - int this_v = (i < this.version.length ? this.version[i] : 0); - int other_v = (i < other.version.length ? other.version[i] : 0); - res = this_v - other_v; - if (res != 0) - break; - } - return res; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/AlienDb.vala shotwell-0.11.92/src/alien_db/AlienDb.vala --- shotwell-0.11.91/src/alien_db/AlienDb.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/AlienDb.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -/* This file is the master unit file for the AlienDb unit. It should be edited to include - * whatever code is deemed necessary. - * - * The init() and terminate() methods are mandatory. - * - * If the unit needs to be configured prior to initialization, add the proper parameters to - * the preconfigure() method, implement it, and ensure in init() that it's been called. - */ - -namespace AlienDb { - -// preconfigure may be deleted if not used. -public void preconfigure() { -} - -public void init() throws Error { - AlienDatabaseHandler.init(); -} - -public void terminate() { - AlienDatabaseHandler.terminate(); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/DiscoveredAlienDatabase.vala shotwell-0.11.92/src/alien_db/DiscoveredAlienDatabase.vala --- shotwell-0.11.91/src/alien_db/DiscoveredAlienDatabase.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/DiscoveredAlienDatabase.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb { - -/** - * A light-weight wrapper that contains enough information to display the - * database entry in the library window but can delay instantiating the - * actual database instance until it is actually needed. - */ -public class DiscoveredAlienDatabase : Object { - private AlienDatabaseID id; - private AlienDatabaseDriver driver; - private AlienDatabase database; - - public DiscoveredAlienDatabase(AlienDatabaseID id) { - this.id = id; - driver = AlienDatabaseHandler.get_instance().get_driver(id.driver_id); - } - - public AlienDatabaseID get_id() { - return id; - } - - public string get_uri() { - return id.to_uri(); - } - - /** - * This method creates an actual instance of the database interface. - * It is called when the application is ready to present the database - * to the user as a page in the main library window. - */ - public AlienDatabase get_database() throws DatabaseError, AlienDatabaseError { - if (database == null) { - database = driver.open_database(id); - } - return database; - } - - /** - * Release the underlying database object. - */ - public void release_database() { - database = null; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/AlienDb.FSpot.vala shotwell-0.11.92/src/alien_db/f_spot/AlienDb.FSpot.vala --- shotwell-0.11.91/src/alien_db/f_spot/AlienDb.FSpot.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/AlienDb.FSpot.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -/* This file is the master unit file for the AlienDb.FSpot unit. It should be edited to include - * whatever code is deemed necessary. - * - * The init() and terminate() methods are mandatory. - * - * If the unit needs to be configured prior to initialization, add the proper parameters to - * the preconfigure() method, implement it, and ensure in init() that it's been called. - */ - -namespace AlienDb.FSpot { - -// preconfigure may be deleted if not used. -public void preconfigure() { -} - -public void init() throws Error { - FSpotDatabaseDriver.init(); - AlienDb.AlienDatabaseHandler.get_instance().register_driver( - FSpotDatabaseDriver.get_instance() - ); -} - -public void terminate() { - AlienDb.AlienDatabaseHandler.get_instance().unregister_driver( - FSpotDatabaseDriver.get_instance() - ); - FSpotDatabaseDriver.terminate(); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseBehavior.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseBehavior.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseBehavior.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseBehavior.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * A class that consolidates the behavior of all F-Spot tables (apart from meta) - * and is the one place to check whether the database version is supported. - */ -public class FSpotDatabaseBehavior : Object { - // Minimum unsupported version: any database from that version and above - // is not supported as it's too new and support has not been provided - // In practice, the code may work with future versions but this cannot be - // guaranteed as it hasn't been tested so it's probably better to just - // bomb out at that point rather than risk importing incorrect data - public static AlienDatabaseVersion MIN_UNSUPPORTED_VERSION = - new AlienDatabaseVersion({ 19 }); - - private FSpotTableBehavior photos_behavior; - private FSpotTableBehavior tags_behavior; - private FSpotTableBehavior photo_tags_behavior; - private FSpotTableBehavior photo_versions_behavior; - private FSpotTableBehavior rolls_behavior; - - public FSpotDatabaseBehavior( - FSpotDatabaseDriver driver, AlienDatabaseVersion version - ) throws AlienDatabaseError { - if (version.compare_to(MIN_UNSUPPORTED_VERSION) >= 0) - throw new AlienDatabaseError.UNSUPPORTED_VERSION("Version %s is not yet supported", version.to_string()); - - FSpotTableBehavior? photos_generic_behavior = driver.find_behavior(FSpotPhotosTable.TABLE_NAME, version); - if (photos_generic_behavior != null) - photos_behavior = photos_generic_behavior as FSpotTableBehavior; - FSpotTableBehavior? tags_generic_behavior = driver.find_behavior(FSpotTagsTable.TABLE_NAME, version); - if (tags_generic_behavior != null) - tags_behavior = tags_generic_behavior as FSpotTableBehavior; - FSpotTableBehavior? photo_tags_generic_behavior = driver.find_behavior(FSpotPhotoTagsTable.TABLE_NAME, version); - if (photo_tags_generic_behavior != null) - photo_tags_behavior = photo_tags_generic_behavior as FSpotTableBehavior; - FSpotTableBehavior? photo_versions_generic_behavior = driver.find_behavior(FSpotPhotoVersionsTable.TABLE_NAME, version); - if (photo_versions_generic_behavior != null) - photo_versions_behavior = photo_versions_generic_behavior as FSpotTableBehavior; - FSpotTableBehavior? rolls_generic_behavior = driver.find_behavior(FSpotRollsTable.TABLE_NAME, version); - if (rolls_generic_behavior != null) - rolls_behavior = rolls_generic_behavior as FSpotTableBehavior; - - if (photos_behavior == null || tags_behavior == null || - photo_tags_behavior == null || photo_versions_behavior == null || - rolls_behavior == null - ) - throw new AlienDatabaseError.UNSUPPORTED_VERSION("Version %s is not supported", version.to_string()); - } - - public FSpotTableBehavior get_photos_behavior() { - return photos_behavior; - } - - public FSpotTableBehavior get_tags_behavior() { - return tags_behavior; - } - - public FSpotTableBehavior get_photo_tags_behavior() { - return photo_tags_behavior; - } - - public FSpotTableBehavior get_photo_versions_behavior() { - return photo_versions_behavior; - } - - public FSpotTableBehavior get_rolls_behavior() { - return rolls_behavior; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseDriver.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseDriver.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseDriver.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseDriver.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,250 +0,0 @@ -/* Copyright 2009-2011 Yorba Foundation - * - * This software is licensed under the GNU LGPL (version 2.1 or later). - * See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -public class FSpotDatabaseDriver : Object, AlienDatabaseDriver { - public static const string FSPOT_DRIVER_ID = "f-spot"; - private static FSpotDatabaseDriver instance; - - /** - * Initialisation method that creates a singleton instance. - */ - public static void init() { - // Check for null in case init() is called more than once. - if(instance == null) - instance = new FSpotDatabaseDriver(); - } - - public static FSpotDatabaseDriver get_instance() { - return instance; - } - - /** - * Termination method that clears the singleton instance. - */ - public static void terminate() { - instance = null; - } - - private class FSpotBehaviorEntry { - private AlienDatabaseVersion version; - private FSpotTableBehavior behavior; - - public FSpotBehaviorEntry(AlienDatabaseVersion version, FSpotTableBehavior behavior) { - this.version = version; - this.behavior = behavior; - } - - public AlienDatabaseVersion get_version() { - return version; - } - - public FSpotTableBehavior get_behavior() { - return behavior; - } - } - - private Gee.Map> behavior_map; - - public FSpotDatabaseDriver() { - behavior_map = new Gee.HashMap>(); - // photos table - Gee.List photos_list = new Gee.ArrayList(); - // v0-4 - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 0 }), - FSpotPhotosV0Behavior.get_instance() - )); - // v5-6 - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 5 }), - FSpotPhotosV5Behavior.get_instance() - )); - // v7-10 - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 7 }), - FSpotPhotosV7Behavior.get_instance() - )); - // v11-15 - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 11 }), - FSpotPhotosV11Behavior.get_instance() - )); - // v16 - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 16 }), - FSpotPhotosV16Behavior.get_instance() - )); - // v17 - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 17 }), - FSpotPhotosV17Behavior.get_instance() - )); - // v18+ - photos_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 18 }), - FSpotPhotosV18Behavior.get_instance() - )); - behavior_map.set(FSpotPhotosTable.TABLE_NAME, photos_list); - // tags table - Gee.List tags_list = new Gee.ArrayList(); - // v0+ - tags_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 0 }), - FSpotTagsV0Behavior.get_instance() - )); - behavior_map.set(FSpotTagsTable.TABLE_NAME, tags_list); - // photo_tags table - Gee.List photo_tags_list = new Gee.ArrayList(); - // v0+ - photo_tags_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 0 }), - FSpotPhotoTagsV0Behavior.get_instance() - )); - behavior_map.set(FSpotPhotoTagsTable.TABLE_NAME, photo_tags_list); - // photo_versions table - Gee.List photo_versions_list = new Gee.ArrayList(); - // v0-8 - photo_versions_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 0 }), - FSpotPhotoVersionsV0Behavior.get_instance() - )); - // v9-15 - photo_versions_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 9 }), - FSpotPhotoVersionsV9Behavior.get_instance() - )); - // v16 - photo_versions_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 16 }), - FSpotPhotoVersionsV16Behavior.get_instance() - )); - // v17 - photo_versions_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 17 }), - FSpotPhotoVersionsV17Behavior.get_instance() - )); - // v18+ - photo_versions_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 18 }), - FSpotPhotoVersionsV18Behavior.get_instance() - )); - behavior_map.set(FSpotPhotoVersionsTable.TABLE_NAME, photo_versions_list); - // rolls table - Gee.List rolls_list = new Gee.ArrayList(); - // v0-4 - rolls_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 0 }), - FSpotRollsV0Behavior.get_instance() - )); - // v5+ - rolls_list.add(new FSpotBehaviorEntry( - new AlienDatabaseVersion({ 5 }), - FSpotRollsV5Behavior.get_instance() - )); - behavior_map.set(FSpotRollsTable.TABLE_NAME, rolls_list); - } - - ~FSpotDatabaseDriver() { - } - - public AlienDatabaseDriverID get_id() { - return new AlienDatabaseDriverID(FSPOT_DRIVER_ID); - } - - public string get_display_name() { - return "F-Spot"; - } - - public Gee.Collection get_discovered_databases() { - Gee.ArrayList discovered_databases = - new Gee.ArrayList(); - - File[] db_files = { - // where the DB is in Ubuntu Lucid - File.new_for_path(Environment.get_user_config_dir()). - get_child("f-spot").get_child("photos.db"), - // where it seems to be in Ubuntu Jaunty - File.new_for_path(Environment.get_home_dir()).get_child(".gnome2"). - get_child("f-spot").get_child("photos.db"), - // where it should really be if it followed the XDG spec - File.new_for_path(Environment.get_user_data_dir()). - get_child("f-spot").get_child("photos.db") - }; - - foreach (File db_file in db_files) { - if (db_file.query_exists(null)) { - discovered_databases.add(new DiscoveredAlienDatabase( - new AlienDatabaseID(get_id(), db_file.get_path()) - )); - message("Discovered database: %s", db_file.get_path()); - } - } - - return discovered_databases; - } - - public FSpotTableBehavior? find_behavior(string table_name, AlienDatabaseVersion version) { - FSpotTableBehavior behavior = null; - Gee.List behavior_list = behavior_map.get(table_name); - if (behavior_list != null) - foreach (FSpotBehaviorEntry entry in behavior_list) { - if (version.compare_to(entry.get_version()) >= 0) - behavior = entry.get_behavior(); - } - else - warning("Could not find behavior list for table %s", table_name); - return behavior; - } - - public AlienDatabase open_database(AlienDatabaseID db_id) throws DatabaseError, AlienDatabaseError { - return new FSpotDatabase(this, db_id); - } - - public AlienDatabase open_database_from_file(File db_file) throws DatabaseError, AlienDatabaseError { - return new FSpotDatabase.from_file(this, db_file); - } - - public string get_menu_name() { - return "ImportFromFSpot"; - } - - public Gtk.ActionEntry get_action_entry() { - Gtk.ActionEntry result = { - "ImportFromFSpot", null, TRANSLATABLE, null, null, on_import_from_fspot - }; - result.label = _("Import From _F-Spot..."); - result.tooltip = _("Import the content of an external F-Spot database"); - return result; - } - - public static bool is_available() { - AlienDatabaseDriver? driver = AlienDatabaseHandler.get_instance().get_driver( - new AlienDatabaseDriverID(FSPOT_DRIVER_ID)); - - return (driver != null) ? driver.get_discovered_databases().size > 0 : false; - } - - public static void do_import(BatchImport.ImportReporter? report_to_when_done = null) { - AlienDatabaseDriver? driver = AlienDatabaseHandler.get_instance().get_driver( - new AlienDatabaseDriverID(FSPOT_DRIVER_ID)); - if (driver == null) - return; - - AlienDatabaseImportDialogController dialog = new AlienDatabaseImportDialogController( - _("Import From F-Spot"), - driver, report_to_when_done); - dialog.execute(); - } - - private static void on_import_from_fspot() { - do_import(); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseEvent.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseEvent.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseEvent.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseEvent.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * The object that implements an F-Spot event and provides access to all the - * elements necessary to read event information. - * Events are a special type of tags as far as FSpot is concered so this - * class wraps a tag row. - */ -public class FSpotDatabaseEvent: Object, AlienDatabaseEvent { - private FSpotTagRow row; - - public FSpotDatabaseEvent(FSpotTagRow row) { - this.row = row; - } - - public string get_name() { - return row.name; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabasePhoto.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabasePhoto.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabasePhoto.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabasePhoto.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * The object that implements an F-Spot photo and provides access to all the - * elements necessary to read data from the photographic source. - */ -public class FSpotDatabasePhoto : Object, AlienDatabasePhoto { - private FSpotPhotoRow photo_row; - private FSpotPhotoVersionRow? photo_version_row; - private FSpotRollRow? roll_row; - private Gee.Collection tags; - private AlienDatabaseEvent? event; - private Rating rating; - - public FSpotDatabasePhoto( - FSpotPhotoRow photo_row, - FSpotPhotoVersionRow? photo_version_row, - FSpotRollRow? roll_row, - Gee.Collection tags, - AlienDatabaseEvent? event, - bool is_hidden, - bool is_favorite - ) { - this.photo_row = photo_row; - this.photo_version_row = photo_version_row; - this.roll_row = roll_row; - this.tags = tags; - this.event = event; - if (photo_row.rating > 0) - this.rating = Rating.unserialize(photo_row.rating); - else if (is_hidden) - this.rating = Rating.REJECTED; - else if (is_favorite) - this.rating = Rating.FIVE; - else - this.rating = Rating.UNRATED; - } - - public string get_folder_path() { - return (photo_version_row != null) ? - photo_version_row.base_path.get_path() : - photo_row.base_path.get_path(); - } - - public string get_filename() { - return (photo_version_row != null) ? - photo_version_row.filename : - photo_row.filename; - } - - public Gee.Collection get_tags() { - return tags; - } - - public AlienDatabaseEvent? get_event() { - return event; - } - - public Rating get_rating() { - return rating; - } - - public string? get_title() { - return is_string_empty(photo_row.description) ? null : photo_row.description; - } - - public ImportID? get_import_id() { - if (roll_row != null) - return ImportID((int64)roll_row.time); - else - return null; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -/* Copyright 2009-2011 Yorba Foundation - * - * This software is licensed under the GNU LGPL (version 2.1 or later). - * See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * This class represents a generic F-Spot table. - */ -public abstract class FSpotDatabaseTable : DatabaseTable { - protected unowned Sqlite.Database fspot_db; - protected FSpotTableBehavior behavior; - - public FSpotDatabaseTable(Sqlite.Database db) { - this.fspot_db = db; - } - - public void set_behavior(FSpotTableBehavior behavior) { - this.behavior = behavior; - set_table_name(behavior.get_table_name()); - } - - public FSpotTableBehavior get_behavior() { - return behavior; - } - - protected string get_joined_column_list(bool with_table = false) { - string[] columns = behavior.list_columns(); - if (with_table) - for (int i = 0; i < columns.length; i++) - columns[i] = "%s.%s".printf(table_name, columns[i]); - return string.joinv(", ", columns); - } - - protected int select_all(out Sqlite.Statement stmt) throws DatabaseError { - string column_list = get_joined_column_list(); - string sql = "SELECT %s FROM %s".printf(column_list, table_name); - - int res = fspot_db.prepare_v2(sql, -1, out stmt); - if (res != Sqlite.OK) - throw_error("Statement failed: %s".printf(sql), res); - - res = stmt.step(); - if (res != Sqlite.ROW && res != Sqlite.DONE) - throw_error("select_all %s %s".printf(table_name, column_list), res); - - return res; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseTag.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseTag.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabaseTag.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabaseTag.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * The object that implements an F-Spot tag and provides access to all the - * elements necessary to read tag information. - */ -public class FSpotDatabaseTag: Object, AlienDatabaseTag { - private FSpotTagRow row; - private FSpotDatabaseTag? parent; - - public FSpotDatabaseTag(FSpotTagRow row, FSpotDatabaseTag? parent = null) { - this.row = row; - this.parent = parent; - } - - public string get_name() { - return row.name; - } - - public AlienDatabaseTag? get_parent() { - return parent; - } - - public FSpotDatabaseTag? get_fspot_parent() { - return parent; - } - - public bool is_stock() { - return (row.stock_icon.has_prefix(FSpotTagsTable.PREFIX_STOCK_ICON)); - } - - public FSpotTagRow get_row() { - return row; - } - - public FSpotDatabaseEvent to_event() { - return new FSpotDatabaseEvent(this.row); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabase.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabase.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotDatabase.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotDatabase.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,210 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -internal class FSpotTagsCache : Object { - private FSpotTagsTable tags_table; - private Gee.HashMap tags_map; - - public FSpotTagsCache(FSpotTagsTable tags_table) throws DatabaseError { - this.tags_table = tags_table; - tags_map = new Gee.HashMap (); - } - - public FSpotDatabaseTag get_tag(FSpotTagRow tag_row) throws DatabaseError { - FSpotDatabaseTag? tag = tags_map.get(tag_row.tag_id); - if (tag != null) { - return tag; - } else { - FSpotDatabaseTag? parent_tag = get_tag_from_id(tag_row.category_id); - FSpotDatabaseTag new_tag = new FSpotDatabaseTag(tag_row, parent_tag); - tags_map[tag_row.tag_id] = new_tag; - return new_tag; - } - } - - private FSpotDatabaseTag? get_tag_from_id(FSpotTagID tag_id) throws DatabaseError { - if (tag_id.is_null() || tag_id.is_invalid()) - return null; - FSpotDatabaseTag? tag = tags_map.get(tag_id); - if (tag != null) - return tag; - FSpotTagRow? tag_row = tags_table.get_by_id(tag_id); - if (tag_row != null) { - FSpotDatabaseTag? parent_tag = get_tag_from_id(tag_row.category_id); - FSpotDatabaseTag new_tag = new FSpotDatabaseTag(tag_row, parent_tag); - tags_map[tag_id] = new_tag; - return new_tag; - } - return null; - } -} - -/** - * An implementation of AlienDatabase that is able to read from the F-Spot - * database and extract the relevant objects. - */ -public class FSpotDatabase : Object, AlienDatabase { - private AlienDatabaseID id; - private Sqlite.Database fspot_db; - private FSpotMetaTable meta_table; - private FSpotPhotosTable photos_table; - private FSpotPhotoVersionsTable photo_versions_table; - private FSpotTagsTable tags_table; - private FSpotTagsCache tags_cache; - private FSpotRollsTable rolls_table; - private int64 hidden_tag_id; - - public FSpotDatabase(FSpotDatabaseDriver driver, AlienDatabaseID id) throws DatabaseError, AlienDatabaseError { - this.id = id; - initialize(driver, id.driver_specific_uri); - } - - public FSpotDatabase.from_file(FSpotDatabaseDriver driver, File db_file) throws DatabaseError, AlienDatabaseError { - this.id = new AlienDatabaseID(driver.get_id(), db_file.get_path()); - initialize(driver, db_file.get_path()); - } - - private void initialize(FSpotDatabaseDriver driver, string filename) throws DatabaseError, AlienDatabaseError { - int res = Sqlite.Database.open_v2(filename, out fspot_db, - Sqlite.OPEN_READONLY, null); - if (res != Sqlite.OK) - throw new DatabaseError.ERROR("Unable to open F-Spot database %s: %d", filename, res); - meta_table = new FSpotMetaTable(fspot_db); - hidden_tag_id = meta_table.get_hidden_tag_id(); - - FSpotDatabaseBehavior db_behavior = new FSpotDatabaseBehavior(driver, get_version()); - - photos_table = new FSpotPhotosTable(fspot_db, db_behavior); - photo_versions_table = new FSpotPhotoVersionsTable(fspot_db, db_behavior); - tags_table = new FSpotTagsTable(fspot_db, db_behavior); - tags_cache = new FSpotTagsCache(tags_table); - rolls_table = new FSpotRollsTable(fspot_db, db_behavior); - } - - ~FSpotDatabase() { - } - - public string get_uri() { - return id.to_uri(); - } - - public string get_display_name() { - return _("F-Spot"); - } - - private AlienDatabaseVersion get_version() throws DatabaseError { - return new AlienDatabaseVersion.from_string(meta_table.get_db_version()); - } - - public Gee.Collection get_photos() throws DatabaseError { - Gee.List photos = new Gee.ArrayList(); - - foreach (FSpotPhotoRow photo_row in photos_table.get_all()) { - bool hidden = false; - bool favorite = false; - Gee.ArrayList tags = new Gee.ArrayList(); - AlienDatabaseEvent? event = null; - FSpotRollRow? roll_row = null; - - // TODO: We do not convert F-Spot events to Shotwell events because F-Spot's events - // are essentially tags. We would need to detect if the tag is an event (use - // is_tag_event) and then assign the event to the photo ... since a photo can be - // in multiple F-Spot events, we would need to pick one, and since their tags - // are heirarchical, we would need to pick a name (probably the leaf) - try { - foreach (FSpotTagRow tag_row in tags_table.get_by_photo_id(photo_row.photo_id)) { - FSpotDatabaseTag tag = tags_cache.get_tag(tag_row); - if (is_tag_hidden(tag)) - hidden = true; - else if (is_tag_favorite(tag)) - favorite = true; - else - tags.add(tag); - } - } catch(DatabaseError e) { - // log the error and leave the tag list empty - message("Failed to retrieve tags for photo ID %ld: %s", (long) photo_row.photo_id.id, - e.message); - } - - try { - roll_row = rolls_table.get_by_id(photo_row.roll_id); - } catch (DatabaseError e) { - // log the error and leave the roll row null - message("Failed to retrieve roll for photo ID %ld: %s", (long) photo_row.photo_id.id, - e.message); - } - - try { - bool photo_versions_added = false; - foreach (FSpotPhotoVersionRow photo_version_row in photo_versions_table.get_by_photo_id(photo_row.photo_id)) { - photos.add(new FSpotDatabasePhoto( - photo_row, photo_version_row, roll_row, tags, event, hidden, favorite - )); - photo_versions_added = true; - } - - // older versions of F-Spot (0.4.3.1 at least, perhaps later) did not maintain photo_versions, - // this handles that case - if (!photo_versions_added) - photos.add(new FSpotDatabasePhoto( - photo_row, null, roll_row, tags, event, hidden, favorite - )); - } catch (DatabaseError e) { - // if we can't load the different versions, do the best we can - // and create one photo from the photo row that was found earlier - message("Failed to retrieve versions for photo ID %ld: %s", (long) photo_row.photo_id.id, - e.message); - photos.add(new FSpotDatabasePhoto( - photo_row, null, roll_row, tags, event, hidden, favorite - )); - } - } - - return photos; - } - - public bool is_tag_event(FSpotDatabaseTag tag) { - bool result = (FSpotTagsTable.STOCK_ICON_EVENTS == tag.get_row().stock_icon); - if (!result) { - FSpotDatabaseTag? parent = tag.get_fspot_parent(); - if (parent == null) - result = false; - else - result = is_tag_event(parent); - } - return result; - } - - public bool is_tag_hidden(FSpotDatabaseTag tag) { - bool result = (hidden_tag_id == tag.get_row().tag_id.id); - if (!result) { - FSpotDatabaseTag? parent = tag.get_fspot_parent(); - if (parent == null) - result = false; - else - result = is_tag_hidden(parent); - } - return result; - } - - public bool is_tag_favorite(FSpotDatabaseTag tag) { - bool result = (FSpotTagsTable.STOCK_ICON_FAV == tag.get_row().stock_icon); - if (!result) { - FSpotDatabaseTag? parent = tag.get_fspot_parent(); - if (parent == null) - result = false; - else - result = is_tag_favorite(parent); - } - return result; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotMetaTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotMetaTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotMetaTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotMetaTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * The value object for the "meta" table, representing a single database row. - */ -public class FSpotMetaRow : Object { - // ignore the ID - public string name; - public string data; -} - -/** - * This class represents the F-Spot meta table, which stores some essential - * meta-data for the whole database. It is implemented as a simple dictionary - * where each row in the table is a key/value pair. - * - * The meta table implementation is the only one that throws a database error - * if something goes wrong because: - * * it is essential to read the content of that table in order to identify - * the version of the database and select the correct behavior, - * * this table is read at the very beginning of the process so any failure - * will occur immediately, - * * failing to read this table means that there is no point in reading the - * attempting to read the rest of the database so we might as well abort. - */ -public class FSpotMetaTable : FSpotDatabaseTable { - - public FSpotMetaTable(Sqlite.Database db) { - base(db); - set_behavior(FSpotMetaBehavior.get_instance()); - } - - public string? get_data(string name) throws DatabaseError { - string[] columns = behavior.list_columns(); - string column_list = string.joinv(", ", columns); - string sql = "SELECT %s FROM %s WHERE name=?".printf(column_list, table_name); - Sqlite.Statement stmt; - int res = fspot_db.prepare_v2(sql, -1, out stmt); - if (res != Sqlite.OK) - throw_error("Statement failed: %s".printf(sql), res); - - res = stmt.bind_text(1, name); - if (res != Sqlite.OK) - throw_error("Bind failed for name %s".printf(name), res); - - res = stmt.step(); - if (res != Sqlite.ROW) { - if (res != Sqlite.DONE) - throw_error("FSpotMetaTable.get_data", res); - - return null; - } - - FSpotMetaRow row; - behavior.build_row(stmt, out row); - return row.data; - } - - public string? get_app_version() throws DatabaseError { - return get_data("F-Spot Version"); - } - - public string? get_db_version() throws DatabaseError { - return get_data("F-Spot Database Version"); - } - - public int64 get_hidden_tag_id() throws DatabaseError { - string id_str = get_data("Hidden Tag Id"); - if(id_str != null) { - return int64.parse(id_str); - } else { - return -1; - } - } -} - -public class FSpotMetaBehavior : FSpotTableBehavior, Object { - public static const string TABLE_NAME = "Meta"; - - private static FSpotMetaBehavior instance; - - private FSpotMetaBehavior() { - } - - public static FSpotMetaBehavior get_instance() { - if (instance == null) - instance = new FSpotMetaBehavior(); - return instance; - } - - public string get_table_name() { - return TABLE_NAME; - } - - public string[] list_columns() { - return { "name", "data" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotMetaRow row, int offset = 0) { - row = new FSpotMetaRow(); - row.name = stmt.column_text(offset + 0); - row.data = stmt.column_text(offset + 1); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotPhotosTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotPhotosTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotPhotosTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotPhotosTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,349 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -public struct FSpotPhotoID { - public const int64 INVALID = -1; - - public int64 id; - - public FSpotPhotoID(int64 id = INVALID) { - this.id = id; - } - - public bool is_invalid() { - return (id == INVALID); - } - - public bool is_valid() { - return (id != INVALID); - } - - public static uint hash(void *a) { - return int64_hash(&((FSpotPhotoID *) a)->id); - } - - public static bool equal(void *a, void *b) { - return ((FSpotPhotoID *) a)->id == ((FSpotPhotoID *) b)->id; - } -} - -/** - * The value object for the "photos" table, representing a single database row. - */ -public class FSpotPhotoRow : Object { - public FSpotPhotoID photo_id; - public time_t time; - public File base_path; - public string filename; - public string description; - public FSpotRollID roll_id; - public FSpotVersionID default_version_id; - public int rating; - public string md5_sum; -} - -/** - * This class represents the F-Spot photos table. - */ -public class FSpotPhotosTable : FSpotDatabaseTable { - public static const string TABLE_NAME = "Photos"; - - public FSpotPhotosTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { - base(db); - set_behavior(db_behavior.get_photos_behavior()); - } - - public Gee.ArrayList get_all() throws DatabaseError { - Gee.ArrayList all = new Gee.ArrayList(); - - Sqlite.Statement stmt; - int res = select_all(out stmt); - while (res == Sqlite.ROW) { - FSpotPhotoRow row; - behavior.build_row(stmt, out row); - all.add(row); - res = stmt.step(); - } - - return all; - } -} - -// Photos table behavior for v0-4 -// The original table format -public class FSpotPhotosV0Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV0Behavior instance; - - private FSpotPhotosV0Behavior() { - } - - public static FSpotPhotosV0Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV0Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "directory_path", "name", "description", - "default_version_id" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - row.base_path = File.new_for_uri(stmt.column_text(offset + 2)); - row.filename = stmt.column_text(offset + 3); - row.description = stmt.column_text(offset + 4); - row.roll_id.id = FSpotRollID.INVALID; - row.default_version_id.id = stmt.column_int64(offset + 5); - row.rating = 0; - row.md5_sum = ""; - } -} - -// Photos table behavior for v5-6 -// v5 introduced a roll_id to reference the imported roll (rolls were a new -// table migrated from imports) -public class FSpotPhotosV5Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV5Behavior instance; - - private FSpotPhotosV5Behavior() { - } - - public static FSpotPhotosV5Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV5Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "directory_path", "name", "description", "roll_id", - "default_version_id" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - row.base_path = File.new_for_uri(stmt.column_text(offset + 2)); - row.filename = stmt.column_text(offset + 3); - row.description = stmt.column_text(offset + 4); - row.roll_id.id = stmt.column_int64(offset + 5); - row.default_version_id.id = stmt.column_int64(offset + 6); - row.rating = 0; - row.md5_sum = ""; - } -} - -// Photos table behavior for v7-10 -// v7 merged directory_path and name into a single URI value with a file:// -// prefix; presumaly this is meant to be able to handle remote files using a -// different URI prefix such as remote files -public class FSpotPhotosV7Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV7Behavior instance; - - private FSpotPhotosV7Behavior() { - } - - public static FSpotPhotosV7Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV7Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "uri", "description", "roll_id", - "default_version_id" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - - File uri = File.new_for_uri(stmt.column_text(offset + 2)); - row.base_path = uri.get_parent(); - row.filename = uri.get_basename(); - - row.description = stmt.column_text(offset + 3); - row.roll_id.id = stmt.column_int64(offset + 4); - row.default_version_id.id = stmt.column_int64(offset + 5); - row.rating = 0; - row.md5_sum = ""; - } -} - -// Photos table behavior for v11-15 -// v11 introduced the concept of rating so add this to the list of fields -public class FSpotPhotosV11Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV11Behavior instance; - - private FSpotPhotosV11Behavior() { - } - - public static FSpotPhotosV11Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV11Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "uri", "description", "roll_id", - "default_version_id", "rating" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - - File uri = File.new_for_uri(stmt.column_text(offset + 2)); - row.base_path = uri.get_parent(); - row.filename = uri.get_basename(); - - row.description = stmt.column_text(offset + 3); - row.roll_id.id = stmt.column_int64(offset + 4); - row.default_version_id.id = stmt.column_int64(offset + 5); - row.rating = stmt.column_int(offset + 6); - row.md5_sum = ""; - } -} - -// Photos table behavior for v16 -// v16 introduced the MD5 sum so add this to the list of fields -public class FSpotPhotosV16Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV16Behavior instance; - - private FSpotPhotosV16Behavior() { - } - - public static FSpotPhotosV16Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV16Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "uri", "description", "roll_id", - "default_version_id", "rating", "md5_sum" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - - File uri = File.new_for_uri(stmt.column_text(offset + 2)); - row.base_path = uri.get_parent(); - row.filename = uri.get_basename(); - - row.description = stmt.column_text(offset + 3); - row.roll_id.id = stmt.column_int64(offset + 4); - row.default_version_id.id = stmt.column_int64(offset + 5); - row.rating = stmt.column_int(offset + 6); - row.md5_sum = stmt.column_text(offset + 7); - } -} - -// Photos table behavior for v17 -// v17 split the URI into base_uri and filename (reverting back to the original -// design introduced in v0, albeit with a URI rather than a file system path) -public class FSpotPhotosV17Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV17Behavior instance; - - private FSpotPhotosV17Behavior() { - } - - public static FSpotPhotosV17Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV17Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "base_uri", "filename", "description", "roll_id", - "default_version_id", "rating", "md5_sum" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - row.base_path = File.new_for_uri(stmt.column_text(offset + 2)); - row.filename = stmt.column_text(offset + 3); - row.description = stmt.column_text(offset + 4); - row.roll_id.id = stmt.column_int64(offset + 5); - row.default_version_id.id = stmt.column_int64(offset + 6); - row.rating = stmt.column_int(offset + 7); - row.md5_sum = stmt.column_text(offset + 8); - } -} - -// v18: no more MD5 hash in the photos table: moved to photo_versions table -public class FSpotPhotosV18Behavior : FSpotTableBehavior, Object { - private static FSpotPhotosV18Behavior instance; - - private FSpotPhotosV18Behavior() { - } - - public static FSpotPhotosV18Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotosV18Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotosTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time", "base_uri", "filename", "description", "roll_id", - "default_version_id", "rating" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) { - row = new FSpotPhotoRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - row.base_path = File.new_for_uri(stmt.column_text(offset + 2)); - row.filename = stmt.column_text(offset + 3); - row.description = stmt.column_text(offset + 4); - row.roll_id.id = stmt.column_int64(offset + 5); - row.default_version_id.id = stmt.column_int64(offset + 6); - row.rating = stmt.column_int(offset + 7); - row.md5_sum = ""; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotPhotoTagsTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotPhotoTagsTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotPhotoTagsTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotPhotoTagsTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * The value object for the "photo_tags" table, representing a single database row. - */ -public class FSpotPhotoTagRow : Object { - public FSpotPhotoID photo_id; - public FSpotTagID tag_id; -} - -/** - * This class represents the F-Spot photo_tags table. - */ -public class FSpotPhotoTagsTable : FSpotDatabaseTable { - public static const string TABLE_NAME = "Photo_Tags"; - - public FSpotPhotoTagsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { - base(db); - set_behavior(db_behavior.get_photo_tags_behavior()); - } -} - -public class FSpotPhotoTagsV0Behavior : FSpotTableBehavior, Object { - private static FSpotPhotoTagsV0Behavior instance; - - private FSpotPhotoTagsV0Behavior() { - } - - public static FSpotPhotoTagsV0Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotoTagsV0Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotoTagsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "photo_id", "tag_id" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoTagRow row, int offset = 0) { - row = new FSpotPhotoTagRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.tag_id.id = stmt.column_int64(offset + 1); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotPhotoVersionsTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotPhotoVersionsTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotPhotoVersionsTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotPhotoVersionsTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,276 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -public struct FSpotVersionID { - public const int64 INVALID = -1; - - public int64 id; - - public FSpotVersionID(int64 id = INVALID) { - this.id = id; - } - - public bool is_invalid() { - return (id == INVALID); - } - - public bool is_valid() { - return (id != INVALID); - } - - public static uint hash(void *a) { - return int64_hash(&((FSpotVersionID *) a)->id); - } - - public static bool equal(void *a, void *b) { - return ((FSpotVersionID *) a)->id == ((FSpotVersionID *) b)->id; - } -} - -/** - * The value object for the "photo_versions" table, representing a single database row. - */ -public class FSpotPhotoVersionRow : Object { - public FSpotPhotoID photo_id; - public FSpotVersionID version_id; - public string name; - public File base_path; - public string filename; - public string md5_sum; - public bool is_protected; -} - -/** - * This class represents the F-Spot photo_versions table. - */ -public class FSpotPhotoVersionsTable : FSpotDatabaseTable { - public static const string TABLE_NAME = "Photo_versions"; - - public FSpotPhotoVersionsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { - base(db); - set_behavior(db_behavior.get_photo_versions_behavior()); - } - - public Gee.ArrayList get_by_photo_id(FSpotPhotoID photo_id) throws DatabaseError { - Gee.ArrayList rows = new Gee.ArrayList(); - - Sqlite.Statement stmt; - - string column_list = get_joined_column_list(); - string sql = "SELECT %s FROM %s WHERE photo_id=?".printf( - column_list, table_name - ); - - int res = fspot_db.prepare_v2(sql, -1, out stmt); - if (res != Sqlite.OK) - throw_error("Statement failed: %s".printf(sql), res); - - res = stmt.bind_int64(1, photo_id.id); - if (res != Sqlite.OK) - throw_error("Bind failed for photo_id", res); - - res = stmt.step(); - while (res == Sqlite.ROW) { - FSpotPhotoVersionRow row; - behavior.build_row(stmt, out row); - rows.add(row); - res = stmt.step(); - } - - return rows; - } -} - -// Photo_versions table behavior for v0-8 -// Note: there is a change in the URI format in version 8 but the FSpotURI -// class should be able to deal with the variation, so the v8 behavior should -// be handled in a way identical to v0-7 -public class FSpotPhotoVersionsV0Behavior : FSpotTableBehavior, Object { - private static FSpotPhotoVersionsV0Behavior instance; - - private FSpotPhotoVersionsV0Behavior() { - } - - public static FSpotPhotoVersionsV0Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotoVersionsV0Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotoVersionsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "photo_id", "version_id", "name", "uri" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { - row = new FSpotPhotoVersionRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.version_id.id = stmt.column_int64(offset + 1); - row.name = stmt.column_text(offset + 2); - - File uri = File.new_for_uri(stmt.column_text(offset + 3)); - row.base_path = uri.get_parent(); - row.filename = uri.get_basename(); - - row.md5_sum = ""; - row.is_protected = false; - } -} - -// Photo_versions table behavior for v9-15 -// add protected field -public class FSpotPhotoVersionsV9Behavior : FSpotTableBehavior, Object { - private static FSpotPhotoVersionsV9Behavior instance; - - private FSpotPhotoVersionsV9Behavior() { - } - - public static FSpotPhotoVersionsV9Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotoVersionsV9Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotoVersionsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "photo_id", "version_id", "name", "uri", - "protected" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { - row = new FSpotPhotoVersionRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.version_id.id = stmt.column_int64(offset + 1); - row.name = stmt.column_text(offset + 2); - - File uri = File.new_for_uri(stmt.column_text(offset + 3)); - row.base_path = uri.get_parent(); - row.filename = uri.get_basename(); - - row.md5_sum = ""; - row.is_protected = (stmt.column_int(offset + 4) > 0); - } -} - -// Photo_versions table behavior for v16 -// add md5_sum in photo_versions -public class FSpotPhotoVersionsV16Behavior : FSpotTableBehavior, Object { - private static FSpotPhotoVersionsV16Behavior instance; - - private FSpotPhotoVersionsV16Behavior() { - } - - public static FSpotPhotoVersionsV16Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotoVersionsV16Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotoVersionsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "photo_id", "version_id", "name", "uri", - "md5_sum", "protected" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { - row = new FSpotPhotoVersionRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.version_id.id = stmt.column_int64(offset + 1); - row.name = stmt.column_text(offset + 2); - - File uri = File.new_for_uri(stmt.column_text(offset + 3)); - row.base_path = uri.get_parent(); - row.filename = uri.get_basename(); - - row.md5_sum = stmt.column_text(offset + 4); - row.is_protected = (stmt.column_int(offset + 5) > 0); - } -} - -// Photo_versions table behavior for v17 -// v17 split the URI into base_uri and filename (reverting back to the original -// design introduced in v0, albeit with a URI rather than a file system path) -public class FSpotPhotoVersionsV17Behavior : FSpotTableBehavior, Object { - private static FSpotPhotoVersionsV17Behavior instance; - - private FSpotPhotoVersionsV17Behavior() { - } - - public static FSpotPhotoVersionsV17Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotoVersionsV17Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotoVersionsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "photo_id", "version_id", "name", "base_uri", "filename", - "md5_sum", "protected" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { - row = new FSpotPhotoVersionRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.version_id.id = stmt.column_int64(offset + 1); - row.name = stmt.column_text(offset + 2); - row.base_path = File.new_for_uri(stmt.column_text(offset + 3)); - row.filename = GLib.Uri.unescape_string(stmt.column_text(offset + 4)); - row.md5_sum = stmt.column_text(offset + 5); - row.is_protected = (stmt.column_int(offset + 6) > 0); - } -} - -// Photo_versions table behavior for v18 -// md5_sum renamed import_md5 -public class FSpotPhotoVersionsV18Behavior : FSpotTableBehavior, Object { - private static FSpotPhotoVersionsV18Behavior instance; - - private FSpotPhotoVersionsV18Behavior() { - } - - public static FSpotPhotoVersionsV18Behavior get_instance() { - if (instance == null) - instance = new FSpotPhotoVersionsV18Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotPhotoVersionsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "photo_id", "version_id", "name", "base_uri", "filename", - "import_md5", "protected" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) { - row = new FSpotPhotoVersionRow(); - row.photo_id.id = stmt.column_int64(offset + 0); - row.version_id.id = stmt.column_int64(offset + 1); - row.name = stmt.column_text(offset + 2); - row.base_path = File.new_for_uri(stmt.column_text(offset + 3)); - row.filename = GLib.Uri.unescape_string(stmt.column_text(offset + 4)); - row.md5_sum = stmt.column_text(offset + 5); - row.is_protected = (stmt.column_int(offset + 6) > 0); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotRollsTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotRollsTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotRollsTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotRollsTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,137 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -public struct FSpotRollID { - public const int64 INVALID = -1; - - public int64 id; - - public FSpotRollID(int64 id = INVALID) { - this.id = id; - } - - public bool is_invalid() { - return (id == INVALID); - } - - public bool is_valid() { - return (id != INVALID); - } - - public static uint hash(void *a) { - return int64_hash(&((FSpotRollID *) a)->id); - } - - public static bool equal(void *a, void *b) { - return ((FSpotRollID *) a)->id == ((FSpotRollID *) b)->id; - } -} - -/** - * The value object for the "rolls" table, representing a single database row. - */ -public class FSpotRollRow : Object { - public FSpotRollID id; - public time_t time; -} - -/** - * This class represents the F-Spot rolls table. - */ -public class FSpotRollsTable : FSpotDatabaseTable { - public static const string TABLE_NAME = "Rolls"; - public static const string TABLE_NAME_PRE_V5 = "Imports"; - - public FSpotRollsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { - base(db); - set_behavior(db_behavior.get_rolls_behavior()); - } - - public FSpotRollRow? get_by_id(FSpotRollID roll_id) throws DatabaseError { - Sqlite.Statement stmt; - FSpotRollRow? row = null; - string column_list = get_joined_column_list(); - string sql = "SELECT %s FROM %s WHERE id=?".printf(column_list, table_name); - - int res = fspot_db.prepare_v2(sql, -1, out stmt); - if (res != Sqlite.OK) - throw_error("Statement failed: %s".printf(sql), res); - - res = stmt.bind_int64(1, roll_id.id); - if (res != Sqlite.OK) - throw_error("Bind failed for roll_id", res); - - res = stmt.step(); - if (res == Sqlite.ROW) - behavior.build_row(stmt, out row); - else if (res == Sqlite.DONE) - message("Could not find roll row with ID %d", (int)roll_id.id); - - return row; - } -} - -// Rolls table behavior for v0-4 -public class FSpotRollsV0Behavior : FSpotTableBehavior, Object { - private static FSpotRollsV0Behavior instance; - - private FSpotRollsV0Behavior() { - } - - public static FSpotRollsV0Behavior get_instance() { - if (instance == null) - instance = new FSpotRollsV0Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotRollsTable.TABLE_NAME_PRE_V5; - } - - public string[] list_columns() { - return { "id", "time" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotRollRow row, int offset = 0) { - row = new FSpotRollRow(); - row.id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - } -} - -// Rolls table behavior for v5+ -// Table name changed from "imports" to "rolls" -public class FSpotRollsV5Behavior : FSpotTableBehavior, Object { - private static FSpotRollsV5Behavior instance; - - private FSpotRollsV5Behavior() { - } - - public static FSpotRollsV5Behavior get_instance() { - if (instance == null) - instance = new FSpotRollsV5Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotRollsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "time" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotRollRow row, int offset = 0) { - row = new FSpotRollRow(); - row.id.id = stmt.column_int64(offset + 0); - row.time = (time_t) stmt.column_int64(offset + 1); - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotTableBehavior.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotTableBehavior.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotTableBehavior.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotTableBehavior.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -/** - * This class defines a generic table behavior. In practice, it implements - * the concept of a DAO (Data Access Object) in ORM terms and is responsible - * for transforming the data extracted from a relational statement into a - * lightweight value object. - * - * The type T defined in the generic is the value object type a behavior - * implementation is designed to handle. Value object types are designed to - * contain the data for a single database row. - */ -public interface FSpotTableBehavior : Object { - public abstract string get_table_name(); - - public abstract string[] list_columns(); - - public abstract void build_row(Sqlite.Statement stmt, out T row, int offset = 0); -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/FSpotTagsTable.vala shotwell-0.11.92/src/alien_db/f_spot/FSpotTagsTable.vala --- shotwell-0.11.91/src/alien_db/f_spot/FSpotTagsTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/FSpotTagsTable.vala 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -/* Copyright 2011 Yorba Foundation - * - * This software is licensed under the GNU Lesser General Public License - * (version 2.1 or later). See the COPYING file in this distribution. - */ - -namespace AlienDb.FSpot { - -// This needs to be a class so that it can be used as a key for a Gee.HashMap -public class FSpotTagID { - public const int64 INVALID = -1; - public const int64 NULL_ID = 0; - - public int64 id; - - public FSpotTagID(int64 id = INVALID) { - this.id = id; - } - - public bool is_invalid() { - return (id == INVALID); - } - - public bool is_valid() { - return (id != INVALID); - } - - public bool is_null() { - return (id == NULL_ID); - } - - public static uint hash(void *a) { - return int64_hash(&((FSpotTagID *) a)->id); - } - - public static bool equal(void *a, void *b) { - return ((FSpotTagID *) a)->id == ((FSpotTagID *) b)->id; - } -} - -/** - * The value object for the "tags" table, representing a single database row. - */ -public class FSpotTagRow : Object { - public FSpotTagID tag_id; - public string name; - public FSpotTagID category_id; - public bool is_category; - public int sort_priority; - public string stock_icon; // only store stock icons -} - -/** - * This class represents the F-Spot tags table. - */ -public class FSpotTagsTable : FSpotDatabaseTable { - public static const string TABLE_NAME = "Tags"; - - public static const string PREFIX_STOCK_ICON = "stock_icon:"; - public static const string STOCK_ICON_FAV = "stock_icon:emblem-favorite"; - public static const string STOCK_ICON_PEOPLE = "stock_icon:emblem-people"; - public static const string STOCK_ICON_PLACES = "stock_icon:emblem-places"; - public static const string STOCK_ICON_EVENTS = "stock_icon:emblem-event"; - - private FSpotTableBehavior photo_tags_behavior; - - public FSpotTagsTable(Sqlite.Database db, FSpotDatabaseBehavior db_behavior) { - base(db); - set_behavior(db_behavior.get_tags_behavior()); - photo_tags_behavior = db_behavior.get_photo_tags_behavior(); - } - - public FSpotTagRow? get_by_id(FSpotTagID tag_id) throws DatabaseError { - Sqlite.Statement stmt; - FSpotTagRow? row = null; - string column_list = get_joined_column_list(); - string sql = "SELECT %s FROM %s WHERE id=?".printf(column_list, table_name); - - int res = fspot_db.prepare_v2(sql, -1, out stmt); - if (res != Sqlite.OK) - throw_error("Statement failed: %s".printf(sql), res); - - res = stmt.bind_int64(1, tag_id.id); - assert(res == Sqlite.OK); - - res = stmt.step(); - if (res == Sqlite.ROW) - behavior.build_row(stmt, out row); - else if (res == Sqlite.DONE) - message("Could not find tag row with ID %d", (int)tag_id.id); - - return row; - } - - public Gee.ArrayList get_by_photo_id(FSpotPhotoID photo_id) throws DatabaseError { - Gee.ArrayList rows = new Gee.ArrayList(); - - Sqlite.Statement stmt; - - string column_list = get_joined_column_list(true); - string sql = "SELECT %1$s FROM %2$s, %3$s WHERE %3$s.photo_id=? AND %3$s.tag_id = %2$s.id".printf( - column_list, table_name, photo_tags_behavior.get_table_name() - ); - - int res = fspot_db.prepare_v2(sql, -1, out stmt); - if (res != Sqlite.OK) - throw_error("Statement failed: %s".printf(sql), res); - - res = stmt.bind_int64(1, photo_id.id); - if (res != Sqlite.OK) - throw_error("Bind failed for photo_id", res); - - res = stmt.step(); - while (res == Sqlite.ROW) { - FSpotTagRow row; - behavior.build_row(stmt, out row); - rows.add(row); - res = stmt.step(); - } - - return rows; - } -} - -public class FSpotTagsV0Behavior : FSpotTableBehavior, Object { - private static FSpotTagsV0Behavior instance; - - private FSpotTagsV0Behavior() { - } - - public static FSpotTagsV0Behavior get_instance() { - if (instance == null) - instance = new FSpotTagsV0Behavior(); - return instance; - } - - public string get_table_name() { - return FSpotTagsTable.TABLE_NAME; - } - - public string[] list_columns() { - return { "id", "name", "category_id", "is_category", "sort_priority", "icon" }; - } - - public void build_row(Sqlite.Statement stmt, out FSpotTagRow row, int offset = 0) { - row = new FSpotTagRow(); - row.tag_id = new FSpotTagID(stmt.column_int64(offset + 0)); - row.name = stmt.column_text(offset + 1); - row.category_id = new FSpotTagID(stmt.column_int64(offset + 2)); - row.is_category = (stmt.column_int(offset + 3) > 0); - row.sort_priority = stmt.column_int(offset + 4); - string icon_str = stmt.column_text(offset + 5); - if (icon_str != null && icon_str.has_prefix(FSpotTagsTable.PREFIX_STOCK_ICON)) - row.stock_icon = icon_str; - else - row.stock_icon = ""; - } -} - -} - diff -Nru shotwell-0.11.91/src/alien_db/f_spot/mk/f_spot.mk shotwell-0.11.92/src/alien_db/f_spot/mk/f_spot.mk --- shotwell-0.11.91/src/alien_db/f_spot/mk/f_spot.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/f_spot/mk/f_spot.mk 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ - -# UNIT_NAME is the Vala namespace. A file named UNIT_NAME.vala must be in this directory with -# a init() and terminate() function declared in the namespace. -UNIT_NAME := AlienDb.FSpot - -# UNIT_DIR should match the subdirectory the files are located in. Generally UNIT_NAME in all -# lowercase. The name of this file should be UNIT_DIR.mk. -UNIT_DIR := alien_db/f_spot - -# All Vala files in the unit should be listed here with no subdirectory prefix. -# -# NOTE: Do *not* include the unit's master file, i.e. UNIT_NAME.vala. -UNIT_FILES := \ - FSpotDatabaseDriver.vala \ - FSpotDatabase.vala \ - FSpotDatabaseBehavior.vala \ - FSpotDatabasePhoto.vala \ - FSpotDatabaseTag.vala \ - FSpotDatabaseEvent.vala \ - FSpotDatabaseTable.vala \ - FSpotTableBehavior.vala \ - FSpotMetaTable.vala \ - FSpotPhotosTable.vala \ - FSpotPhotoVersionsTable.vala \ - FSpotTagsTable.vala \ - FSpotPhotoTagsTable.vala \ - FSpotRollsTable.vala - -# Any unit this unit relies upon (and should be initialized before it's initialized) should -# be listed here using its Vala namespace. -# -# NOTE: All units are assumed to rely upon the unit-unit. Do not include that here. -UNIT_USES := \ - AlienDb - -# List any additional files that are used in the build process as a part of this unit that should -# be packaged in the tarball. File names should be relative to the unit's home directory. -UNIT_RC := - -# unitize.mk must be called at the end of each UNIT_DIR.mk file. -include unitize.mk - diff -Nru shotwell-0.11.91/src/alien_db/mk/alien_db.mk shotwell-0.11.92/src/alien_db/mk/alien_db.mk --- shotwell-0.11.91/src/alien_db/mk/alien_db.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/alien_db/mk/alien_db.mk 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ - -# UNIT_NAME is the Vala namespace. A file named UNIT_NAME.vala must be in this directory with -# a init() and terminate() function declared in the namespace. -UNIT_NAME := AlienDb - -# UNIT_DIR should match the subdirectory the files are located in. Generally UNIT_NAME in all -# lowercase. The name of this file should be UNIT_DIR.mk. -UNIT_DIR := alien_db - -# All Vala files in the unit should be listed here with no subdirectory prefix. -# -# NOTE: Do *not* include the unit's master file, i.e. UNIT_NAME.vala. -UNIT_FILES := \ - AlienDatabase.vala \ - AlienDatabaseHandler.vala \ - AlienDatabaseDriver.vala \ - DiscoveredAlienDatabase.vala \ - AlienDatabasePhoto.vala \ - AlienDatabaseTag.vala \ - AlienDatabaseEvent.vala \ - AlienDatabaseVersion.vala \ - AlienDatabaseImportJob.vala \ - AlienDatabaseImportSource.vala \ - AlienDatabaseImportDialog.vala \ - AlienDatabaseImportDialogController.vala - -# Any unit this unit relies upon (and should be initialized before it's initialized) should -# be listed here using its Vala namespace. -# -# NOTE: All units are assumed to rely upon the unit-unit. Do not include that here. -UNIT_USES := - -# List any additional files that are used in the build process as a part of this unit that should -# be packaged in the tarball. File names should be relative to the unit's home directory. -UNIT_RC := - -# unitize.mk must be called at the end of each UNIT_DIR.mk file. -include unitize.mk - diff -Nru shotwell-0.11.91/src/AppDirs.vala shotwell-0.11.92/src/AppDirs.vala --- shotwell-0.11.91/src/AppDirs.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/AppDirs.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Application.vala shotwell-0.11.92/src/Application.vala --- shotwell-0.11.91/src/Application.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Application.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/AppWindow.vala shotwell-0.11.92/src/AppWindow.vala --- shotwell-0.11.91/src/AppWindow.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/AppWindow.vala 2012-02-21 00:41:45.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/BatchImport.vala shotwell-0.11.92/src/BatchImport.vala --- shotwell-0.11.91/src/BatchImport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/BatchImport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Box.vala shotwell-0.11.92/src/Box.vala --- shotwell-0.11.91/src/Box.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Box.vala 2012-02-20 20:47:45.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -77,6 +77,11 @@ int.max(corner1.x, corner2.x), int.max(corner1.y, corner2.y)); } + public static Box from_center(Gdk.Point center, int width, int height) { + return Box(center.x - (width / 2), center.y - (height / 2), + center.x + (width / 2), center.y + (height / 2)); + } + public int get_width() { assert(right >= left); @@ -97,6 +102,20 @@ return (left == box.left && top == box.top && right == box.right && bottom == box.bottom); } + // Adjust width, preserving the box's center. + public void adjust_width(int width) { + int center_x = (left + right) / 2; + left = center_x - (width / 2); + right = center_x + (width / 2); + } + + // Adjust height, preserving the box's center. + public void adjust_height(int height) { + int center_y = (top + bottom) / 2; + top = center_y - (height / 2); + bottom = center_y + (height / 2); + } + public Box get_scaled(Dimensions scaled) { double x_scale, y_scale; get_dimensions().get_scale_ratios(scaled, out x_scale, out y_scale); @@ -156,6 +175,10 @@ return rect; } + public Gdk.Point get_center() { + return { (left + right) / 2, (top + bottom) / 2 }; + } + public Box rotate_clockwise(Dimensions space) { int l = space.width - bottom - 1; int t = left; diff -Nru shotwell-0.11.91/src/camera/Branch.vala shotwell-0.11.92/src/camera/Branch.vala --- shotwell-0.11.91/src/camera/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/camera/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/camera/CameraTable.vala shotwell-0.11.92/src/camera/CameraTable.vala --- shotwell-0.11.91/src/camera/CameraTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/camera/CameraTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -208,7 +208,7 @@ private string? get_name_for_uuid(string uuid) { foreach (Volume volume in volume_monitor.get_volumes()) { - if (volume.get_identifier(VOLUME_IDENTIFIER_KIND_UUID) == uuid) { + if (volume.get_identifier(VolumeIdentifier.UUID) == uuid) { return volume.get_name(); } } @@ -217,7 +217,7 @@ private GLib.Icon? get_icon_for_uuid(string uuid) { foreach (Volume volume in volume_monitor.get_volumes()) { - if (volume.get_identifier(VOLUME_IDENTIFIER_KIND_UUID) == uuid) { + if (volume.get_identifier(VolumeIdentifier.UUID) == uuid) { return volume.get_icon(); } } diff -Nru shotwell-0.11.91/src/camera/Camera.vala shotwell-0.11.92/src/camera/Camera.vala --- shotwell-0.11.91/src/camera/Camera.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/camera/Camera.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/camera/GPhoto.vala shotwell-0.11.92/src/camera/GPhoto.vala --- shotwell-0.11.91/src/camera/GPhoto.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/camera/GPhoto.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -201,11 +201,12 @@ // if entire file fits in memory, return a stream from that ... can't merely wrap // MemoryInputStream around the camera_file buffer, as that will be destroyed when the // function returns - unowned uint8[] data; - res = camera_file.get_data_and_size(out data); + unowned uint8 *data; + ulong data_len; + res = camera_file.get_data_and_size(out data, out data_len); if (res == Result.OK) { - uint8[] buffer = new uint8[data.length]; - Memory.copy(buffer, data, data.length); + uint8[] buffer = new uint8[data_len]; + Memory.copy(buffer, data, buffer.length); return new MemoryInputStream.from_data(buffer, on_mins_destroyed); } @@ -239,12 +240,13 @@ // if buffer can be loaded into memory, return a copy of that (can't return buffer itself // as it will be destroyed when the camera_file is unref'd) - unowned uint8[] data; - res = camera_file.get_data_and_size(out data); + unowned uint8 *data; + ulong data_len; + res = camera_file.get_data_and_size(out data, out data_len); if (res != Result.OK) return null; - uint8[] buffer = new uint8[data.length]; + uint8[] buffer = new uint8[data_len]; Memory.copy(buffer, data, buffer.length); return buffer; diff -Nru shotwell-0.11.91/src/camera/ImportPage.vala shotwell-0.11.92/src/camera/ImportPage.vala --- shotwell-0.11.91/src/camera/ImportPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/camera/ImportPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/CheckerboardLayout.vala shotwell-0.11.92/src/CheckerboardLayout.vala --- shotwell-0.11.91/src/CheckerboardLayout.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/CheckerboardLayout.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -460,15 +460,16 @@ return null; } - public void paint(Cairo.Context ctx, Gdk.Color bg_color, Gdk.Color selected_color, - Gdk.Color text_color, Gdk.Color? border_color) { + public void paint(Cairo.Context ctx, Gdk.RGBA bg_color, Gdk.RGBA selected_color, + Gdk.RGBA text_color, Gdk.RGBA? border_color) { // calc the top-left point of the pixbuf Gdk.Point pixbuf_origin = Gdk.Point(); pixbuf_origin.x = allocation.x + FRAME_WIDTH + BORDER_WIDTH; pixbuf_origin.y = allocation.y + FRAME_WIDTH + BORDER_WIDTH; ctx.set_line_width(FRAME_WIDTH); - Gdk.cairo_set_source_color(ctx, selected_color); + ctx.set_source_rgba(selected_color.red, selected_color.green, selected_color.blue, + selected_color.alpha); // draw shadow if (border_color != null) { @@ -492,27 +493,30 @@ // draw border if (border_color != null) { ctx.save(); - Gdk.cairo_set_source_color(ctx, border_color); + ctx.set_source_rgba(border_color.red, border_color.green, border_color.blue, + border_color.alpha); paint_border(ctx, pixbuf_dim, pixbuf_origin, BORDER_WIDTH); ctx.restore(); } if (display_pixbuf != null) { ctx.save(); - Gdk.cairo_set_source_color(ctx, bg_color); + ctx.set_source_rgba(bg_color.red, bg_color.green, bg_color.blue, bg_color.alpha); paint_image(ctx, display_pixbuf, pixbuf_origin); ctx.restore(); } - Gdk.cairo_set_source_color(ctx, text_color); + ctx.set_source_rgba(text_color.red, text_color.green, text_color.blue, text_color.alpha); // title and subtitles are LABEL_PADDING below bottom of pixbuf int text_y = allocation.y + FRAME_WIDTH + pixbuf_dim.height + FRAME_WIDTH + LABEL_PADDING; if (title != null && title_visible) { // get the layout sized so its with is no more than the pixbuf's // resize the text width to be no more than the pixbuf's - title.allocation = { allocation.x + FRAME_WIDTH, text_y, pixbuf_dim.width, - title.get_height() }; + title.allocation.x = allocation.x + FRAME_WIDTH; + title.allocation.y = text_y; + title.allocation.width = pixbuf_dim.width; + title.allocation.height = title.get_height(); ctx.move_to(title.allocation.x, title.allocation.y); Pango.cairo_show_layout(ctx, title.get_pango_layout(pixbuf_dim.width)); @@ -521,8 +525,10 @@ } if (subtitle != null && subtitle_visible) { - subtitle.allocation = { allocation.x + FRAME_WIDTH, text_y, pixbuf_dim.width, - subtitle.get_height() }; + subtitle.allocation.x = allocation.x + FRAME_WIDTH; + subtitle.allocation.y = text_y; + subtitle.allocation.width = pixbuf_dim.width; + subtitle.allocation.height = subtitle.get_height(); ctx.move_to(subtitle.allocation.x, subtitle.allocation.y); Pango.cairo_show_layout(ctx, subtitle.get_pango_layout(pixbuf_dim.width)); @@ -530,7 +536,8 @@ // increment text_y if more text lines follow } - Gdk.cairo_set_source_color(ctx, selected_color); + ctx.set_source_rgba(selected_color.red, selected_color.green, selected_color.blue, + selected_color.alpha); // draw trinkets last Gdk.Pixbuf? trinket = get_bottom_left_trinket(TRINKET_SCALE); @@ -690,10 +697,10 @@ private Gtk.Adjustment hadjustment = null; private Gtk.Adjustment vadjustment = null; private string message = null; - private Gdk.Color selected_color; - private Gdk.Color unselected_color; - private Gdk.Color border_color; - private Gdk.Color bg_color; + private Gdk.RGBA selected_color; + private Gdk.RGBA unselected_color; + private Gdk.RGBA border_color; + private Gdk.RGBA bg_color; private Gdk.Rectangle visible_page = Gdk.Rectangle(); private int last_width = 0; private int columns = 0; @@ -726,7 +733,7 @@ view.items_selected.connect(on_items_selection_changed); view.items_unselected.connect(on_items_selection_changed); - modify_bg(Gtk.StateType.NORMAL, Config.Facade.get_instance().get_bg_color()); + override_background_color(Gtk.StateFlags.NORMAL, Config.Facade.get_instance().get_bg_color()); Config.Facade.get_instance().colors_changed.connect(on_colors_changed); @@ -1565,7 +1572,10 @@ assert(ypadding >= 0); // save pixel and grid coordinates - item.allocation = { x + xpadding, y + ypadding, req.width, req.height }; + item.allocation.x = x + xpadding; + item.allocation.y = y + ypadding; + item.allocation.width = req.width; + item.allocation.height = req.height; item.set_grid_coordinates(col, row); // add to current row in spatial data structure @@ -1661,13 +1671,10 @@ private void set_colors(bool in_focus = true) { // set up selected/unselected colors - selected_color = fetch_color( - Config.Facade.get_instance().get_selected_color(in_focus).to_string()); - unselected_color = fetch_color( - Config.Facade.get_instance().get_unselected_color().to_string()); - border_color = fetch_color( - Config.Facade.get_instance().get_border_color().to_string()); - bg_color = this.get_style().bg[Gtk.StateType.NORMAL]; + selected_color = Config.Facade.get_instance().get_selected_color(in_focus); + unselected_color = Config.Facade.get_instance().get_unselected_color(); + border_color = Config.Facade.get_instance().get_border_color(); + bg_color = get_style_context().get_background_color(Gtk.StateFlags.NORMAL); } public override void size_allocate(Gtk.Allocation allocation) { @@ -1713,7 +1720,7 @@ int y = allocation.height - text_height; y = (y > 0) ? y / 2 : 0; - Gdk.cairo_set_source_color(ctx, unselected_color); + ctx.set_source_rgb(unselected_color.red, unselected_color.green, unselected_color.blue); ctx.move_to(x, y); Pango.cairo_show_layout(ctx, pango_layout); } @@ -1742,7 +1749,8 @@ // pixelate selection rectangle interior if (visible_band.width > 1 && visible_band.height > 1) { - set_source_color_with_alpha(ctx, selected_color, SELECTION_ALPHA); + ctx.set_source_rgba(selected_color.red, selected_color.green, selected_color.blue, + SELECTION_ALPHA); ctx.rectangle(visible_band.x, visible_band.y, visible_band.width, visible_band.height); ctx.fill(); @@ -1753,7 +1761,7 @@ // http://cairographics.org/FAQ/#sharp_lines ctx.set_line_width(1.0); ctx.set_line_cap(Cairo.LineCap.SQUARE); - Gdk.cairo_set_source_color(ctx, selected_color); + ctx.set_source_rgb(selected_color.red, selected_color.green, selected_color.blue); ctx.rectangle((double) selection_band.x + 0.5, (double) selection_band.y + 0.5, (double) selection_band.width - 1.0, (double) selection_band.height - 1.0); ctx.stroke(); @@ -1766,7 +1774,7 @@ } private void on_colors_changed() { - modify_bg(Gtk.StateType.NORMAL, Config.Facade.get_instance().get_bg_color()); + override_background_color(Gtk.StateFlags.NORMAL, Config.Facade.get_instance().get_bg_color()); set_colors(); } diff -Nru shotwell-0.11.91/src/CollectionPage.vala shotwell-0.11.92/src/CollectionPage.vala --- shotwell-0.11.91/src/CollectionPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/CollectionPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/ColorTransformation.vala shotwell-0.11.92/src/ColorTransformation.vala --- shotwell-0.11.91/src/ColorTransformation.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/ColorTransformation.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/CommandManager.vala shotwell-0.11.92/src/CommandManager.vala --- shotwell-0.11.91/src/CommandManager.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/CommandManager.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Commands.vala shotwell-0.11.92/src/Commands.vala --- shotwell-0.11.91/src/Commands.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Commands.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -722,15 +722,18 @@ public class StraightenCommand : GenericPhotoTransformationCommand { private double theta; + private Box crop; // straightening can change the crop rectangle - public StraightenCommand(Photo photo, double theta, string name, string explanation) { + public StraightenCommand(Photo photo, double theta, Box crop, string name, string explanation) { base(photo, name, explanation); this.theta = theta; + this.crop = crop; } public override void execute_on_photo(Photo photo) { photo.set_straighten(theta); + photo.set_crop(crop); } } diff -Nru shotwell-0.11.91/src/config/ConfigurationInterfaces.vala shotwell-0.11.92/src/config/ConfigurationInterfaces.vala --- shotwell-0.11.91/src/config/ConfigurationInterfaces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/config/ConfigurationInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -47,6 +47,7 @@ LAST_CROP_MENU_CHOICE, LAST_CROP_WIDTH, LAST_USED_SERVICE, + LAST_USED_DATAIMPORTS_SERVICE, LIBRARY_PHOTOS_SORT_ASCENDING, LIBRARY_PHOTOS_SORT_BY, LIBRARY_WINDOW_HEIGHT, @@ -160,6 +161,9 @@ case LAST_USED_SERVICE: return "LAST_USED_SERVICE"; + case LAST_USED_DATAIMPORTS_SERVICE: + return "LAST_USED_DATAIMPORTS_SERVICE"; + case LIBRARY_PHOTOS_SORT_ASCENDING: return "LIBRARY_PHOTOS_SORT_ASCENDING"; @@ -882,6 +886,30 @@ } // + // last used import service + // + public virtual string get_last_used_dataimports_service() { + try { + return get_engine().get_string_property(ConfigurableProperty.LAST_USED_DATAIMPORTS_SERVICE); + } catch (ConfigurationError err) { + on_configuration_error(err); + // in the event we can't get a reasonable value from the configuration engine, we + // return the empty string since it won't match the name of any existing import + // service -- this will cause the import subsystem to select the first service + // loaded + return ""; + } + } + + public virtual void set_last_used_dataimports_service(string service_name) { + try { + get_engine().set_string_property(ConfigurableProperty.LAST_USED_DATAIMPORTS_SERVICE, service_name); + } catch (ConfigurationError err) { + on_configuration_error(err); + } + } + + // // library photos sort // public virtual void get_library_photos_sort(out bool sort_order, out int sort_by) { diff -Nru shotwell-0.11.91/src/config/Config.vala shotwell-0.11.92/src/config/Config.vala --- shotwell-0.11.91/src/config/Config.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/config/Config.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -29,7 +29,7 @@ public const string DEFAULT_BG_COLOR = "#444"; public const int NO_VIDEO_INTERPRETER_STATE = -1; - private const uint BLACK_THRESHOLD = 40000; + private const double BLACK_THRESHOLD = 0.61; private const string DARK_SELECTED_COLOR = "#0AD"; private const string LIGHT_SELECTED_COLOR = "#2DF"; private const string DARK_UNSELECTED_COLOR = "#000"; @@ -66,7 +66,7 @@ colors_changed(); } - private void set_text_colors(Gdk.Color bg_color) { + private void set_text_colors(Gdk.RGBA bg_color) { // since bg color is greyscale, we only need to compare the red value to the threshold, // which determines whether the background is dark enough to need light text and selection // colors or vice versa @@ -92,14 +92,14 @@ set_text_colors(parse_color(bg_color)); } - public Gdk.Color get_bg_color() { + public Gdk.RGBA get_bg_color() { if (is_string_empty(bg_color)) get_colors(); return parse_color(bg_color); } - public Gdk.Color get_selected_color(bool in_focus = true) { + public Gdk.RGBA get_selected_color(bool in_focus = true) { if (in_focus) { if (is_string_empty(selected_color)) get_colors(); @@ -113,21 +113,21 @@ } } - public Gdk.Color get_unselected_color() { + public Gdk.RGBA get_unselected_color() { if (is_string_empty(unselected_color)) get_colors(); return parse_color(unselected_color); } - public Gdk.Color get_border_color() { + public Gdk.RGBA get_border_color() { if (is_string_empty(border_color)) get_colors(); return parse_color(border_color); } - public void set_bg_color(Gdk.Color color) { + public void set_bg_color(Gdk.RGBA color) { bg_color = color.to_string(); set_bg_color_name(bg_color); diff -Nru shotwell-0.11.91/src/config/GSettingsEngine.vala shotwell-0.11.92/src/config/GSettingsEngine.vala --- shotwell-0.11.91/src/config/GSettingsEngine.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/config/GSettingsEngine.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -15,6 +15,7 @@ private const string VIDEO_SCHEMA_NAME = ROOT_SCHEMA_NAME + ".video"; private const string PRINTING_SCHEMA_NAME = ROOT_SCHEMA_NAME + ".printing"; private const string SHARING_SCHEMA_NAME = ROOT_SCHEMA_NAME + ".sharing"; + private const string IMPORTING_SCHEMA_NAME = ROOT_SCHEMA_NAME + ".dataimports"; private const string CROP_SCHEMA_NAME = ROOT_SCHEMA_NAME + ".crop-settings"; private const string SYSTEM_DESKTOP_SCHEMA_NAME = "org.gnome.desktop.background"; private const string PLUGINS_ENABLE_DISABLE_SCHEMA_NAME = ROOT_SCHEMA_NAME + @@ -59,6 +60,7 @@ schema_names[ConfigurableProperty.LAST_CROP_MENU_CHOICE] = CROP_SCHEMA_NAME; schema_names[ConfigurableProperty.LAST_CROP_WIDTH] = CROP_SCHEMA_NAME; schema_names[ConfigurableProperty.LAST_USED_SERVICE] = SHARING_SCHEMA_NAME; + schema_names[ConfigurableProperty.LAST_USED_DATAIMPORTS_SERVICE] = IMPORTING_SCHEMA_NAME; schema_names[ConfigurableProperty.LIBRARY_PHOTOS_SORT_ASCENDING] = UI_PREFS_SCHEMA_NAME; schema_names[ConfigurableProperty.LIBRARY_PHOTOS_SORT_BY] = UI_PREFS_SCHEMA_NAME; schema_names[ConfigurableProperty.LIBRARY_WINDOW_HEIGHT] = WINDOW_PREFS_SCHEMA_NAME; @@ -115,6 +117,7 @@ key_names[ConfigurableProperty.LAST_CROP_MENU_CHOICE] = "last-crop-menu-choice"; key_names[ConfigurableProperty.LAST_CROP_WIDTH] = "last-crop-width"; key_names[ConfigurableProperty.LAST_USED_SERVICE] = "last-used-service"; + key_names[ConfigurableProperty.LAST_USED_DATAIMPORTS_SERVICE] = "last-used-dataimports-service"; key_names[ConfigurableProperty.LIBRARY_PHOTOS_SORT_ASCENDING] = "library-photos-sort-ascending"; key_names[ConfigurableProperty.LIBRARY_PHOTOS_SORT_BY] = "library-photos-sort-by"; key_names[ConfigurableProperty.LIBRARY_WINDOW_HEIGHT] = "library-height"; diff -Nru shotwell-0.11.91/src/core/Alteration.vala shotwell-0.11.92/src/core/Alteration.vala --- shotwell-0.11.91/src/core/Alteration.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/Alteration.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/ContainerSourceCollection.vala shotwell-0.11.92/src/core/ContainerSourceCollection.vala --- shotwell-0.11.91/src/core/ContainerSourceCollection.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/ContainerSourceCollection.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/Core.vala shotwell-0.11.92/src/core/Core.vala --- shotwell-0.11.91/src/core/Core.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/Core.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DatabaseSourceCollection.vala shotwell-0.11.92/src/core/DatabaseSourceCollection.vala --- shotwell-0.11.91/src/core/DatabaseSourceCollection.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DatabaseSourceCollection.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataCollection.vala shotwell-0.11.92/src/core/DataCollection.vala --- shotwell-0.11.91/src/core/DataCollection.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataCollection.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataObject.vala shotwell-0.11.92/src/core/DataObject.vala --- shotwell-0.11.91/src/core/DataObject.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataObject.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataSet.vala shotwell-0.11.92/src/core/DataSet.vala --- shotwell-0.11.91/src/core/DataSet.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataSet.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataSourceTypes.vala shotwell-0.11.92/src/core/DataSourceTypes.vala --- shotwell-0.11.91/src/core/DataSourceTypes.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataSourceTypes.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataSource.vala shotwell-0.11.92/src/core/DataSource.vala --- shotwell-0.11.91/src/core/DataSource.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataSource.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataViewTypes.vala shotwell-0.11.92/src/core/DataViewTypes.vala --- shotwell-0.11.91/src/core/DataViewTypes.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataViewTypes.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/DataView.vala shotwell-0.11.92/src/core/DataView.vala --- shotwell-0.11.91/src/core/DataView.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/DataView.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/SourceCollection.vala shotwell-0.11.92/src/core/SourceCollection.vala --- shotwell-0.11.91/src/core/SourceCollection.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/SourceCollection.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/SourceHoldingTank.vala shotwell-0.11.92/src/core/SourceHoldingTank.vala --- shotwell-0.11.91/src/core/SourceHoldingTank.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/SourceHoldingTank.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/SourceInterfaces.vala shotwell-0.11.92/src/core/SourceInterfaces.vala --- shotwell-0.11.91/src/core/SourceInterfaces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/SourceInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/Tracker.vala shotwell-0.11.92/src/core/Tracker.vala --- shotwell-0.11.91/src/core/Tracker.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/Tracker.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/util.vala shotwell-0.11.92/src/core/util.vala --- shotwell-0.11.91/src/core/util.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/util.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/core/ViewCollection.vala shotwell-0.11.92/src/core/ViewCollection.vala --- shotwell-0.11.91/src/core/ViewCollection.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/core/ViewCollection.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/CustomComponents.vala shotwell-0.11.92/src/CustomComponents.vala --- shotwell-0.11.91/src/CustomComponents.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/CustomComponents.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/data_imports/DataImportJob.vala shotwell-0.11.92/src/data_imports/DataImportJob.vala --- shotwell-0.11.91/src/data_imports/DataImportJob.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/data_imports/DataImportJob.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,177 @@ +/* Copyright 2009-2011 Yorba Foundation + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ + +namespace Spit.DataImports { + +/** + * A specialized import job implementation for alien databases. + */ +public class DataImportJob : BatchImportJob { + private DataImportSource import_source; + private File? src_file; + private uint64 filesize; + private time_t exposure_time; + private DataImportJob? associated = null; + private HierarchicalTagIndex? detected_htags = null; + + public DataImportJob(DataImportSource import_source) { + this.import_source = import_source; + + // stash everything called in prepare(), as it may/will be called from a separate thread + src_file = import_source.get_file(); + filesize = import_source.get_filesize(); + exposure_time = import_source.get_exposure_time(); + } + + private HierarchicalTagIndex? build_exclusion_index(ImportableTag[] src_tags) { + Gee.Set detected_htags = new Gee.HashSet(); + + foreach (ImportableTag src_tag in src_tags) { + string? prepped = HierarchicalTagUtilities.join_path_components( + Tag.prep_tag_names( + build_path_components(src_tag) + ) + ); + + if (prepped != null && prepped.has_prefix(Tag.PATH_SEPARATOR_STRING)) { + detected_htags.add(prepped); + + Gee.List parents = HierarchicalTagUtilities.enumerate_parent_paths(prepped); + foreach (string parent in parents) + detected_htags.add(parent); + } + } + + return (detected_htags.size > 0) ? HierarchicalTagIndex.from_paths(detected_htags) : null; + } + + public time_t get_exposure_time() { + return exposure_time; + } + + public override string get_dest_identifier() { + return import_source.get_filename(); + } + + public override string get_source_identifier() { + return import_source.get_filename(); + } + + public override bool is_directory() { + return false; + } + + public override string get_basename() { + return src_file.get_basename(); + } + + public override string get_path() { + return src_file.get_parent().get_path(); + } + + public override void set_associated(BatchImportJob associated) { + this.associated = associated as DataImportJob; + } + + public override bool determine_file_size(out uint64 filesize, out File file) { + file = null; + filesize = this.filesize; + + return true; + } + + public override bool prepare(out File file_to_import, out bool copy_to_library) throws Error { + file_to_import = src_file; + copy_to_library = false; + + detected_htags = build_exclusion_index(import_source.get_photo().get_tags()); + + return true; + } + + public override bool complete(MediaSource source, BatchImportRoll import_roll) throws Error { + LibraryPhoto? photo = source as LibraryPhoto; + if (photo == null) + return false; + + ImportableMediaItem src_photo = import_source.get_photo(); + + // tags + if (detected_htags != null) { + Gee.Collection paths = detected_htags.get_all_paths(); + + foreach (string path in paths) + Tag.for_path(path); + } + + ImportableTag[] src_tags = src_photo.get_tags(); + foreach (ImportableTag src_tag in src_tags) { + string? prepped = HierarchicalTagUtilities.join_path_components( + Tag.prep_tag_names( + build_path_components(src_tag) + ) + ); + if (prepped != null) { + if (HierarchicalTagUtilities.enumerate_path_components(prepped).size == 1) { + if (prepped.has_prefix(Tag.PATH_SEPARATOR_STRING)) + prepped = HierarchicalTagUtilities.hierarchical_to_flat(prepped); + } else { + Gee.List parents = + HierarchicalTagUtilities.enumerate_parent_paths(prepped); + + assert(parents.size > 0); + + string top_level_parent = parents.get(0); + string flat_top_level_parent = + HierarchicalTagUtilities.hierarchical_to_flat(top_level_parent); + + if (Tag.global.exists(flat_top_level_parent)) + Tag.for_path(flat_top_level_parent).promote(); + } + + Tag.for_path(prepped).attach(photo); + } + } + // event + ImportableEvent? src_event = src_photo.get_event(); + if (src_event != null) { + string? prepped = prepare_input_text(src_event.get_name(), + PrepareInputTextOptions.DEFAULT, -1); + if (prepped != null) + Event.generate_single_event(photo, import_roll.generated_events, prepped); + } + // rating + Rating dst_rating; + ImportableRating src_rating = src_photo.get_rating(); + if (src_rating.is_rejected()) + dst_rating = Rating.REJECTED; + else if (src_rating.is_unrated()) + dst_rating = Rating.UNRATED; + else + dst_rating = Rating.unserialize(src_rating.get_value()); + photo.set_rating(dst_rating); + // title + string? title = src_photo.get_title(); + if (title != null) + photo.set_title(title); + // import ID + photo.set_import_id(import_roll.import_id); + + return true; + } + + private string[] build_path_components(ImportableTag tag) { + // use a linked list as we are always inserting in head position + Gee.List components = new Gee.LinkedList(); + for (ImportableTag current_tag = tag; current_tag != null; current_tag = current_tag.get_parent()) { + components.insert(0, HierarchicalTagUtilities.make_flat_tag_safe(current_tag.get_name())); + } + return components.to_array(); + } +} + +} + diff -Nru shotwell-0.11.91/src/data_imports/DataImportSource.vala shotwell-0.11.92/src/data_imports/DataImportSource.vala --- shotwell-0.11.91/src/data_imports/DataImportSource.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/data_imports/DataImportSource.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,135 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace Spit.DataImports { + +/** + * Photo source implementation for alien databases. This class is responsible + * for extracting meta-data out of a source photo to support the import + * process. + * + * This class does not extend PhotoSource in order to minimise the API to the + * absolute minimum required to run the import job. + */ +public class DataImportSource { + private bool backing_file_found; + private ImportableMediaItem db_photo; + private string? title = null; + private string? preview_md5 = null; + private uint64 file_size; + private time_t modification_time; + private MetadataDateTime? exposure_time; + + public DataImportSource(ImportableMediaItem db_photo) { + this.db_photo = db_photo; + + // A well-behaved plugin will ensure that the path and file name are + // not null but we check just in case + string folder_path = db_photo.get_folder_path(); + string filename = db_photo.get_filename(); + File? photo = null; + if (folder_path != null && filename != null) { + photo = File.new_for_path(db_photo.get_folder_path()). + get_child(db_photo.get_filename()); + + backing_file_found = photo.query_exists(); + } else { + backing_file_found = false; + } + + if (photo != null && backing_file_found) { + PhotoMetadata? metadata = new PhotoMetadata(); + try { + metadata.read_from_file(photo); + } catch(Error e) { + warning("Could not get file metadata for %s: %s", get_filename(), e.message); + metadata = null; + } + + title = (metadata != null) ? metadata.get_title() : null; + exposure_time = (metadata != null) ? metadata.get_exposure_date_time() : null; + PhotoPreview? preview = metadata != null ? metadata.get_preview(0) : null; + if (preview != null) { + try { + uint8[] preview_raw = preview.flatten(); + preview_md5 = md5_binary(preview_raw, preview_raw.length); + } catch(Error e) { + warning("Could not get raw preview for %s: %s", get_filename(), e.message); + } + } +#if TRACE_MD5 + debug("Photo MD5 %s: preview=%s", get_filename(), preview_md5); +#endif + + try { + file_size = query_total_file_size(photo); + } catch(Error e) { + warning("Could not get file size for %s: %s", get_filename(), e.message); + } + try { + modification_time = query_file_modified(photo); + } catch(Error e) { + warning("Could not get modification time for %s: %s", get_filename(), e.message); + } + } else { + debug ("Photo file %s not found".printf(photo.get_path())); + } + } + + public string get_filename() { + return db_photo.get_filename(); + } + + public string get_fulldir() { + return db_photo.get_folder_path(); + } + + public File get_file() { + return File.new_for_path(get_fulldir()).get_child(get_filename()); + } + + public string get_name() { + return !is_string_empty(title) ? title : get_filename(); + } + + public string? get_title() { + return title; + } + + public PhotoFileFormat get_file_format() { + return PhotoFileFormat.get_by_basename_extension(get_filename()); + } + + public string to_string() { + return get_name(); + } + + public time_t get_exposure_time() { + return (exposure_time != null) ? exposure_time.get_timestamp() : modification_time; + } + + public uint64 get_filesize() { + return file_size; + } + + public ImportableMediaItem get_photo() { + return db_photo; + } + + public bool is_already_imported() { + // ignore trashed duplicates + return (preview_md5 != null) + ? LibraryPhoto.has_nontrash_duplicate(null, preview_md5, null, get_file_format()) + : false; + } + + public bool was_backing_file_found() { + return backing_file_found; + } +} + +} + diff -Nru shotwell-0.11.91/src/data_imports/DataImportsPluginHost.vala shotwell-0.11.92/src/data_imports/DataImportsPluginHost.vala --- shotwell-0.11.91/src/data_imports/DataImportsPluginHost.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/data_imports/DataImportsPluginHost.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,482 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace Spit.DataImports { + +private class CoreImporter { + private weak Spit.DataImports.PluginHost host; + public int imported_items_count = 0; + public BatchImportRoll? current_import_roll = null; + + public CoreImporter(Spit.DataImports.PluginHost host) { + this.host = host; + } + + public void prepare_media_items_for_import( + ImportableMediaItem[] items, + double progress, + double host_progress_delta = 0.0, + string? progress_message = null + ) { + host.update_import_progress_pane(progress, progress_message); + // + SortedList jobs = + new SortedList(import_job_comparator); + Gee.ArrayList already_imported = + new Gee.ArrayList(); + Gee.ArrayList failed = + new Gee.ArrayList(); + + int item_idx = 0; + double item_progress_delta = host_progress_delta / items.length; + foreach (ImportableMediaItem src_item in items) { + DataImportSource import_source = new DataImportSource(src_item); + + if (!import_source.was_backing_file_found()) { + message("Skipping import of %s: backing file not found", + import_source.get_filename()); + failed.add(new DataImportJob(import_source)); + + continue; + } + + if (import_source.is_already_imported()) { + message("Skipping import of %s: checksum detected in library", + import_source.get_filename()); + already_imported.add(new DataImportJob(import_source)); + + continue; + } + + jobs.add(new DataImportJob(import_source)); + item_idx++; + host.update_import_progress_pane(progress + item_idx * item_progress_delta); + } + + if (jobs.size > 0) { + // If there it no current import roll, create one to ensure that all + // imported items end up in the same roll even if this method is called + // several times + if (current_import_roll == null) + current_import_roll = new BatchImportRoll(); + string db_name = _("%s Database").printf(host.get_data_importer().get_service().get_pluggable_name()); + BatchImport batch_import = new BatchImport(jobs, db_name, data_import_reporter, + failed, already_imported, null, current_import_roll); + + LibraryWindow.get_app().enqueue_batch_import(batch_import, true); + imported_items_count += jobs.size; + } + + host.update_import_progress_pane(progress + host_progress_delta); + } + + public void finalize_import() { + // Send an empty job to the queue to mark the end of the import + string db_name = _("%s Database").printf(host.get_data_importer().get_service().get_pluggable_name()); + BatchImport batch_import = new BatchImport( + new Gee.ArrayList(), db_name, data_import_reporter, null, null, null, current_import_roll + ); + LibraryWindow.get_app().enqueue_batch_import(batch_import, true); + current_import_roll = null; + } +} + +public class ConcreteDataImportsHost : Plugins.StandardHostInterface, + Spit.DataImports.PluginHost { + + private Spit.DataImports.DataImporter active_importer = null; + private weak DataImportsUI.DataImportsDialog dialog = null; + private DataImportsUI.ProgressPane? progress_pane = null; + private bool importing_halted = false; + private CoreImporter core_importer; + + public ConcreteDataImportsHost(Service service, DataImportsUI.DataImportsDialog dialog) { + base(service, "data_imports"); + this.dialog = dialog; + + this.active_importer = service.create_data_importer(this); + this.core_importer = new CoreImporter(this); + } + + public DataImporter get_data_importer() { + return active_importer; + } + + public void start_importing() { + if (get_data_importer().is_running()) + return; + + debug("ConcreteDataImportsHost.start_importing( ): invoked."); + + get_data_importer().start(); + } + + public void stop_importing() { + debug("ConcreteDataImportsHost.stop_importing( ): invoked."); + + if (get_data_importer().is_running()) + get_data_importer().stop(); + + clean_up(); + + importing_halted = true; + } + + private void clean_up() { + progress_pane = null; + } + + public void set_button_mode(Spit.DataImports.PluginHost.ButtonMode mode) { + if (mode == Spit.DataImports.PluginHost.ButtonMode.CLOSE) + dialog.set_close_button_mode(); + else if (mode == Spit.DataImports.PluginHost.ButtonMode.CANCEL) + dialog.set_cancel_button_mode(); + else + error("unrecognized button mode enumeration value"); + } + + // Pane handling methods + + public void post_error(Error err) { + post_error_message(err.message); + } + + public void post_error_message(string message) { + string msg = _("Importing from %s can't continue because an error occurred:").printf( + active_importer.get_service().get_pluggable_name()); + msg += GLib.Markup.printf_escaped("\n\n%s\n\n", message); + msg += _("To try importing from another service, select one from the above menu."); + + dialog.install_pane(new DataImportsUI.StaticMessagePane.with_pango(msg)); + dialog.set_close_button_mode(); + dialog.unlock_service(); + + get_data_importer().stop(); + + // post_error_message( ) tells the active_importer to stop importing and displays a + // non-removable error pane that effectively ends the publishing interaction, + // so no problem calling clean_up( ) here. + clean_up(); + } + + public void install_dialog_pane(Spit.DataImports.DialogPane pane, + Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) { + debug("DataImports.PluginHost: install_dialog_pane( ): invoked."); + + if (get_data_importer() == null || (!get_data_importer().is_running())) + return; + + dialog.install_pane(pane); + + set_button_mode(button_mode); + } + + public void install_static_message_pane(string message, + Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) { + + set_button_mode(button_mode); + + dialog.install_pane(new DataImportsUI.StaticMessagePane.with_pango(message)); + } + + public void install_library_selection_pane( + string welcome_message, + ImportableLibrary[] discovered_libraries, + string? file_select_label + ) { + if (discovered_libraries.length == 0 && file_select_label == null) + post_error_message("Libraries or file option needed"); + else + dialog.install_pane(new DataImportsUI.LibrarySelectionPane( + this, + welcome_message, + discovered_libraries, + file_select_label + )); + set_button_mode(Spit.DataImports.PluginHost.ButtonMode.CLOSE); + } + + public void install_import_progress_pane( + string message + ) { + progress_pane = new DataImportsUI.ProgressPane(message); + dialog.install_pane(progress_pane); + set_button_mode(Spit.DataImports.PluginHost.ButtonMode.CANCEL); + // initialize the import + core_importer.imported_items_count = 0; + core_importer.current_import_roll = null; + } + + public void update_import_progress_pane( + double progress, + string? progress_message = null + ) { + if (progress_pane != null) { + progress_pane.update_progress(progress, progress_message); + } + } + + public void prepare_media_items_for_import( + ImportableMediaItem[] items, + double progress, + double host_progress_delta = 0.0, + string? progress_message = null + ) { + core_importer.prepare_media_items_for_import(items, progress, host_progress_delta, progress_message); + } + + public void finalize_import( + ImportedItemsCountCallback report_imported_items_count, + string? finalize_message = null + ) { + update_import_progress_pane(1.0, finalize_message); + set_button_mode(Spit.DataImports.PluginHost.ButtonMode.CLOSE); + core_importer.finalize_import(); + report_imported_items_count(core_importer.imported_items_count); + if (core_importer.imported_items_count > 0) + LibraryWindow.get_app().switch_to_import_queue_page(); + } +} + +public class WelcomeDataImportsHost : Plugins.StandardHostInterface, + Spit.DataImports.PluginHost { + + private weak WelcomeImportMetaHost meta_host; + private Spit.DataImports.DataImporter active_importer = null; + private bool importing_halted = false; + private CoreImporter core_importer; + + public WelcomeDataImportsHost(Service service, WelcomeImportMetaHost meta_host) { + base(service, "data_imports"); + + this.active_importer = service.create_data_importer(this); + this.core_importer = new CoreImporter(this); + this.meta_host = meta_host; + } + + public DataImporter get_data_importer() { + return active_importer; + } + + public void start_importing() { + if (get_data_importer().is_running()) + return; + + debug("WelcomeDataImportsHost.start_importing( ): invoked."); + + get_data_importer().start(); + } + + public void stop_importing() { + debug("WelcomeDataImportsHost.stop_importing( ): invoked."); + + if (get_data_importer().is_running()) + get_data_importer().stop(); + + clean_up(); + + importing_halted = true; + } + + private void clean_up() { + } + + // Pane handling methods + + public void post_error(Error err) { + post_error_message(err.message); + } + + public void post_error_message(string message) { + string msg = _("Importing from %s can't continue because an error occurred:").printf( + active_importer.get_service().get_pluggable_name()); + + debug(msg); + + get_data_importer().stop(); + + // post_error_message( ) tells the active_importer to stop importing and displays a + // non-removable error pane that effectively ends the publishing interaction, + // so no problem calling clean_up( ) here. + clean_up(); + } + + public void install_dialog_pane(Spit.DataImports.DialogPane pane, + Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) { + // do nothing + } + + public void install_static_message_pane(string message, + Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) { + // do nothing + } + + public void install_library_selection_pane( + string welcome_message, + ImportableLibrary[] discovered_libraries, + string? file_select_label + ) { + debug("WelcomeDataImportsHost: Installing library selection pane for %s".printf(get_data_importer().get_service().get_pluggable_name())); + if (discovered_libraries.length > 0) { + meta_host.install_service_entry(new WelcomeImportServiceEntry( + this, + get_data_importer().get_service().get_pluggable_name(), + discovered_libraries + )); + } + } + + public void install_import_progress_pane( + string message + ) { + // empty implementation + } + + public void update_import_progress_pane( + double progress, + string? progress_message = null + ) { + // empty implementation + } + + public void prepare_media_items_for_import( + ImportableMediaItem[] items, + double progress, + double host_progress_delta = 0.0, + string? progress_message = null + ) { + core_importer.prepare_media_items_for_import(items, progress, host_progress_delta, progress_message); + } + + public void finalize_import( + ImportedItemsCountCallback report_imported_items_count, + string? finalize_message = null + ) { + core_importer.finalize_import(); + report_imported_items_count(core_importer.imported_items_count); + meta_host.finalize_import(this); + } +} + + +//public delegate void WelcomeImporterCallback(); + +public class WelcomeImportServiceEntry : GLib.Object, WelcomeServiceEntry { + private string pluggable_name; + private ImportableLibrary[] discovered_libraries; + private Spit.DataImports.PluginHost host; + + public WelcomeImportServiceEntry( + Spit.DataImports.PluginHost host, + string pluggable_name, ImportableLibrary[] discovered_libraries) { + + this.host = host; + this.pluggable_name = pluggable_name; + this.discovered_libraries = discovered_libraries; + } + + public string get_service_name() { + return pluggable_name; + } + + public void execute() { + foreach (ImportableLibrary library in discovered_libraries) { + host.get_data_importer().on_library_selected(library); + } + } +} + +public class WelcomeImportMetaHost : GLib.Object { + private WelcomeDialog dialog; + + public WelcomeImportMetaHost(WelcomeDialog dialog) { + this.dialog = dialog; + } + + public void start() { + Service[] services = load_all_services(); + foreach (Service service in services) { + WelcomeDataImportsHost host = new WelcomeDataImportsHost(service, this); + host.start_importing(); + } + } + + public void finalize_import(WelcomeDataImportsHost host) { + host.stop_importing(); + } + + public void install_service_entry(WelcomeServiceEntry entry) { + debug("WelcomeImportMetaHost: Installing service entry for %s".printf(entry.get_service_name())); + dialog.install_service_entry(entry); + } +} + +public static Spit.DataImports.Service[] load_all_services() { + return load_services(true); +} + +public static Spit.DataImports.Service[] load_services(bool load_all = false) { + Spit.DataImports.Service[] loaded_services = new Spit.DataImports.Service[0]; + + // load publishing services from plug-ins + Gee.Collection pluggables = Plugins.get_pluggables_for_type( + typeof(Spit.DataImports.Service), null, load_all); + // TODO: include sorting function to ensure consistent order + + debug("DataImportsDialog: discovered %d pluggable data import services.", pluggables.size); + + foreach (Spit.Pluggable pluggable in pluggables) { + int pluggable_interface = pluggable.get_pluggable_interface( + Spit.DataImports.CURRENT_INTERFACE, Spit.DataImports.CURRENT_INTERFACE); + if (pluggable_interface != Spit.DataImports.CURRENT_INTERFACE) { + warning("Unable to load data import plugin %s: reported interface %d.", + Plugins.get_pluggable_module_id(pluggable), pluggable_interface); + + continue; + } + + Spit.DataImports.Service service = + (Spit.DataImports.Service) pluggable; + + debug("DataImportsDialog: discovered pluggable data import service '%s'.", + service.get_pluggable_name()); + + loaded_services += service; + } + + // Sort import services by name. + // TODO: extract to a function to sort it on initial request + Posix.qsort(loaded_services, loaded_services.length, sizeof(Spit.DataImports.Service), + (a, b) => {return utf8_cs_compare((*((Spit.DataImports.Service**) a))->get_pluggable_name(), + (*((Spit.DataImports.Service**) b))->get_pluggable_name()); + }); + + return loaded_services; +} + +private ImportManifest? meta_manifest = null; + +private void data_import_reporter(ImportManifest manifest, BatchImportRoll import_roll) { + if (manifest.all.size > 0) { + if (meta_manifest == null) + meta_manifest = new ImportManifest(); + foreach (BatchImportResult result in manifest.all) { + meta_manifest.add_result(result); + } + } else { + DataImportsUI.DataImportsDialog.terminate_instance(); + ImportUI.report_manifest(meta_manifest, true); + meta_manifest = null; + } +} + +private int64 import_job_comparator(void *a, void *b) { + return ((DataImportJob *) a)->get_exposure_time() + - ((DataImportJob *) b)->get_exposure_time(); +} + +} + diff -Nru shotwell-0.11.91/src/data_imports/DataImportsUI.vala shotwell-0.11.92/src/data_imports/DataImportsUI.vala --- shotwell-0.11.91/src/data_imports/DataImportsUI.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/data_imports/DataImportsUI.vala 2012-02-20 22:59:53.000000000 +0000 @@ -0,0 +1,428 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace DataImportsUI { + +public class ConcreteDialogPane : Spit.DataImports.DialogPane, GLib.Object { + private Gtk.VBox pane_widget; + + public ConcreteDialogPane() { + pane_widget = new Gtk.VBox(false, 8); + } + + public Gtk.Widget get_widget() { + return pane_widget; + } + + public Spit.DataImports.DialogPane.GeometryOptions get_preferred_geometry() { + return Spit.DataImports.DialogPane.GeometryOptions.NONE; + } + + public void on_pane_installed() { + } + + public void on_pane_uninstalled() { + } +} + +public class StaticMessagePane : ConcreteDialogPane { + public StaticMessagePane(string message_string) { + Gtk.Label message_label = new Gtk.Label(message_string); + (get_widget() as Gtk.Container).add(message_label); + } + + public StaticMessagePane.with_pango(string msg) { + Gtk.Label label = new Gtk.Label(null); + label.set_markup(msg); + label.set_line_wrap(true); + + (get_widget() as Gtk.Container).add(label); + } +} + +public class LibrarySelectionPane : ConcreteDialogPane { + private weak Spit.DataImports.PluginHost host; + private Spit.DataImports.ImportableLibrary? selected_library = null; + private File? selected_file = null; + private Gtk.Button import_button; + private Gtk.RadioButton? file_radio = null; + + public LibrarySelectionPane( + Spit.DataImports.PluginHost host, + string welcome_message, + Spit.DataImports.ImportableLibrary[] discovered_libraries, + string? file_select_label + ) { + assert(discovered_libraries.length > 0 || on_file_selected != null); + + this.host = host; + + Gtk.Box content_box = new Gtk.VBox(false, 8); + content_box.set_margin_left(30); + content_box.set_margin_right(30); + Gtk.Label welcome_label = new Gtk.Label(null); + welcome_label.set_markup(welcome_message); + welcome_label.set_line_wrap(true); + welcome_label.set_halign(Gtk.Align.START); + content_box.pack_start(welcome_label, true, true, 6); + + // margins for buttons + int radio_margin_left = 20; + int radio_margin_right = 20; + int chooser_margin_left = radio_margin_left; + int chooser_margin_right = radio_margin_right; + + Gtk.RadioButton lib_radio = null; + if (discovered_libraries.length > 0) { + chooser_margin_left = radio_margin_left + 20; + foreach (Spit.DataImports.ImportableLibrary library in discovered_libraries) { + string lib_radio_label = library.get_display_name(); + lib_radio = create_radio_button( + content_box, lib_radio, library, lib_radio_label, + radio_margin_left, radio_margin_right + ); + } + if (file_select_label != null) { + lib_radio = create_radio_button( + content_box, lib_radio, null, file_select_label, + radio_margin_left, radio_margin_right + ); + file_radio = lib_radio; + } + } + if (file_select_label != null) { + Gtk.FileChooserButton file_chooser = new Gtk.FileChooserButton(_("Database file:"), Gtk.FileChooserAction.OPEN); + file_chooser.selection_changed.connect(() => { + selected_file = file_chooser.get_file(); + if (file_radio != null) + file_radio.active = true; + set_import_button_sensitivity(); + }); + file_chooser.set_margin_left(chooser_margin_left); + file_chooser.set_margin_right(chooser_margin_right); + content_box.pack_start(file_chooser, false, false, 6); + } + + import_button = new Gtk.Button.with_mnemonic(_("_Import")); + import_button.clicked.connect(() => { + if (selected_library != null) + on_library_selected(selected_library); + else if (selected_file != null) + on_file_selected(selected_file); + else + debug("LibrarySelectionPane: Library or file should be selected."); + }); + Gtk.ButtonBox button_box = new Gtk.HButtonBox(); + button_box.layout_style = Gtk.ButtonBoxStyle.CENTER; + button_box.add(import_button); + content_box.pack_end(button_box, true, false, 6); + + (get_widget() as Gtk.Container).add(content_box); + + set_import_button_sensitivity(); + } + + private Gtk.RadioButton create_radio_button( + Gtk.Box box, Gtk.RadioButton? group, Spit.DataImports.ImportableLibrary? library, string label, + int margin_left, int margin_right + ) { + var button = new Gtk.RadioButton.with_label_from_widget (group, label); + if (group == null) { // first radio button is active + button.active = true; + selected_library = library; + } + button.toggled.connect (() => { + if (button.active) { + this.selected_library = library; + set_import_button_sensitivity(); + } + + }); + button.set_margin_left(margin_left); + button.set_margin_right(margin_right); + box.pack_start(button, false, false, 6); + return button; + } + + private void set_import_button_sensitivity() { + import_button.set_sensitive(selected_library != null || selected_file != null); + } + + private void on_library_selected(Spit.DataImports.ImportableLibrary library) { + host.get_data_importer().on_library_selected(library); + } + + private void on_file_selected(File file) { + host.get_data_importer().on_file_selected(file); + } +} + +public class ProgressPane : ConcreteDialogPane { + private Gtk.Label message_label; + private Gtk.Label progress_label; + private Gtk.ProgressBar progress_bar; + + public ProgressPane(string message) { + Gtk.Box content_box = new Gtk.VBox(false, 8); + message_label = new Gtk.Label(message); + content_box.pack_start(message_label, true, true, 6); + progress_bar = new Gtk.ProgressBar(); + content_box.pack_start(progress_bar, false, true, 6); + progress_label = new Gtk.Label(""); + content_box.pack_start(progress_label, false, true, 6); + + (get_widget() as Gtk.Container).add(content_box); + } + + public void update_progress(double progress, string? progress_message) { + progress_bar.set_fraction(progress); + if (progress_message != null) + progress_label.set_label(progress_message); + spin_event_loop(); + } +} + +public class DataImportsDialog : Gtk.Dialog { + private const int LARGE_WINDOW_WIDTH = 860; + private const int LARGE_WINDOW_HEIGHT = 688; + private const int COLOSSAL_WINDOW_WIDTH = 1024; + private const int COLOSSAL_WINDOW_HEIGHT = 688; + private const int STANDARD_WINDOW_WIDTH = 600; + private const int STANDARD_WINDOW_HEIGHT = 510; + private const int BORDER_REGION_WIDTH = 16; + private const int BORDER_REGION_HEIGHT = 100; + + public const int STANDARD_CONTENT_LABEL_WIDTH = 500; + public const int STANDARD_ACTION_BUTTON_WIDTH = 128; + + private Gtk.ComboBoxText service_selector_box; + private Gtk.Label service_selector_box_label; + private Gtk.VBox central_area_layouter; + private Gtk.Button close_cancel_button; + private Spit.DataImports.DialogPane active_pane; + private Spit.DataImports.ConcreteDataImportsHost host; + + protected DataImportsDialog() { + + resizable = false; + delete_event.connect(on_window_close); + + string title = _("Import From Application"); + string label = _("Import media _from:"); + + set_title(title); + + service_selector_box = new Gtk.ComboBoxText(); + service_selector_box.set_active(0); + service_selector_box_label = new Gtk.Label.with_mnemonic(label); + service_selector_box_label.set_mnemonic_widget(service_selector_box); + service_selector_box_label.set_alignment(0.0f, 0.5f); + + // get the name of the service the user last used + string? last_used_service = Config.Facade.get_instance().get_last_used_dataimports_service(); + + Spit.DataImports.Service[] loaded_services = Spit.DataImports.load_services(); + int ticker = 0; + int last_used_index = -1; + foreach (Spit.DataImports.Service service in loaded_services) { + string curr_service_id = service.get_id(); + if (last_used_service != null && last_used_service == curr_service_id) + last_used_index = ticker; + + service_selector_box.append_text(service.get_pluggable_name()); + ticker++; + } + if (last_used_index >= 0) + service_selector_box.set_active(last_used_index); + else + service_selector_box.set_active(0); + + service_selector_box.changed.connect(on_service_changed); + + /* the wrapper is not an extraneous widget -- it's necessary to prevent the service + selection box from growing and shrinking whenever its parent's size changes. + When wrapped inside a Gtk.Alignment, the Alignment grows and shrinks instead of + the service selection box. */ + Gtk.Alignment service_selector_box_wrapper = new Gtk.Alignment(1.0f, 0.5f, 0.0f, 0.0f); + service_selector_box_wrapper.add(service_selector_box); + + Gtk.HBox service_selector_layouter = new Gtk.HBox(false, 8); + service_selector_layouter.set_border_width(12); + service_selector_layouter.add(service_selector_box_label); + service_selector_layouter.add(service_selector_box_wrapper); + + /* 'service area' is the selector assembly plus the horizontal rule dividing it from the + rest of the dialog */ + Gtk.VBox service_area_layouter = new Gtk.VBox(false, 0); + service_area_layouter.add(service_selector_layouter); + Gtk.HSeparator service_central_separator = new Gtk.HSeparator(); + service_area_layouter.add(service_central_separator); + + Gtk.Alignment service_area_wrapper = new Gtk.Alignment(0.0f, 0.0f, 1.0f, 0.0f); + service_area_wrapper.add(service_area_layouter); + + central_area_layouter = new Gtk.VBox(false, 0); + + ((Gtk.Box) get_content_area()).pack_start(service_area_wrapper, false, false, 0); + ((Gtk.Box) get_content_area()).pack_start(central_area_layouter, true, true, 0); + + close_cancel_button = new Gtk.Button.with_mnemonic("_Cancel"); + close_cancel_button.set_can_default(true); + close_cancel_button.clicked.connect(on_close_cancel_clicked); + ((Gtk.Box) get_action_area()).add(close_cancel_button); + + set_standard_window_mode(); + + // trigger the selected service + on_service_changed(); + + show_all(); + } + + public static DataImportsDialog get_or_create_instance() { + if (instance == null) { + instance = new DataImportsDialog(); + } + return instance; + } + + public static void terminate_instance() { + if (instance != null) { + instance.terminate(); + } + instance = null; + } + + private bool on_window_close(Gdk.EventAny evt) { + host.stop_importing(); + host = null; + hide(); + destroy(); + + return true; + } + + private void on_service_changed() { + debug("DataImportsDialog: on_service_changed invoked."); + string service_name = service_selector_box.get_active_text(); + + Spit.DataImports.Service? selected_service = null; + Spit.DataImports.Service[] services = Spit.DataImports.load_all_services(); + foreach (Spit.DataImports.Service service in services) { + if (service.get_pluggable_name() == service_name) { + selected_service = service; + break; + } + } + assert(selected_service != null); + + Config.Facade.get_instance().set_last_used_dataimports_service(selected_service.get_id()); + + host = new Spit.DataImports.ConcreteDataImportsHost(selected_service, this); + host.start_importing(); + } + + private void on_close_cancel_clicked() { + debug("DataImportsDialog: on_close_cancel_clicked( ): invoked."); + + terminate(); + } + + private void terminate() { + debug("DataImportsDialog: terminate( ): invoked."); + + host.stop_importing(); + host = null; + hide(); + destroy(); + } + + private void set_large_window_mode() { + set_size_request(LARGE_WINDOW_WIDTH, LARGE_WINDOW_HEIGHT); + central_area_layouter.set_size_request(LARGE_WINDOW_WIDTH - BORDER_REGION_WIDTH, + LARGE_WINDOW_HEIGHT - BORDER_REGION_HEIGHT); + resizable = false; + } + + private void set_colossal_window_mode() { + set_size_request(COLOSSAL_WINDOW_WIDTH, COLOSSAL_WINDOW_HEIGHT); + central_area_layouter.set_size_request(COLOSSAL_WINDOW_WIDTH - BORDER_REGION_WIDTH, + COLOSSAL_WINDOW_HEIGHT - BORDER_REGION_HEIGHT); + resizable = false; + } + + private void set_standard_window_mode() { + set_size_request(STANDARD_WINDOW_WIDTH, STANDARD_WINDOW_HEIGHT); + central_area_layouter.set_size_request(STANDARD_WINDOW_WIDTH - BORDER_REGION_WIDTH, + STANDARD_WINDOW_HEIGHT - BORDER_REGION_HEIGHT); + resizable = false; + } + + private void set_free_sizable_window_mode() { + resizable = true; + } + + private void clear_free_sizable_window_mode() { + resizable = false; + } + + public Spit.DataImports.DialogPane get_active_pane() { + return active_pane; + } + + public void set_close_button_mode() { + close_cancel_button.set_label(_("_Close")); + set_default(close_cancel_button); + } + + public void set_cancel_button_mode() { + close_cancel_button.set_label(_("_Cancel")); + } + + public void lock_service() { + service_selector_box.set_sensitive(false); + } + + public void unlock_service() { + service_selector_box.set_sensitive(true); + } + + public void install_pane(Spit.DataImports.DialogPane pane) { + debug("DataImportsDialog: install_pane( ): invoked."); + + if (active_pane != null) { + debug("DataImportsDialog: install_pane( ): a pane is already installed; removing it."); + + active_pane.on_pane_uninstalled(); + central_area_layouter.remove(active_pane.get_widget()); + } + + central_area_layouter.add(pane.get_widget()); + show_all(); + + Spit.DataImports.DialogPane.GeometryOptions geometry_options = + pane.get_preferred_geometry(); + if ((geometry_options & Spit.Publishing.DialogPane.GeometryOptions.EXTENDED_SIZE) != 0) + set_large_window_mode(); + else if ((geometry_options & Spit.Publishing.DialogPane.GeometryOptions.COLOSSAL_SIZE) != 0) + set_colossal_window_mode(); + else + set_standard_window_mode(); + + if ((geometry_options & Spit.Publishing.DialogPane.GeometryOptions.RESIZABLE) != 0) + set_free_sizable_window_mode(); + else + clear_free_sizable_window_mode(); + + active_pane = pane; + pane.on_pane_installed(); + } + + private static DataImportsDialog? instance; +} + +} + diff -Nru shotwell-0.11.91/src/data_imports/DataImports.vala shotwell-0.11.92/src/data_imports/DataImports.vala --- shotwell-0.11.91/src/data_imports/DataImports.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/data_imports/DataImports.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,30 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +/* This file is the master unit file for the DataImports unit. It should be edited to include + * whatever code is deemed necessary. + * + * The init() and terminate() methods are mandatory. + * + * If the unit needs to be configured prior to initialization, add the proper parameters to + * the preconfigure() method, implement it, and ensure in init() that it's been called. + */ + +namespace DataImports { + +public void init() throws Error { + string[] core_ids = new string[0]; + core_ids += "org.yorba.shotwell.dataimports.fspot"; + + Plugins.register_extension_point(typeof(Spit.DataImports.Service), _("Data Imports"), + Resources.IMPORT, core_ids); +} + +public void terminate() { +} + +} + diff -Nru shotwell-0.11.91/src/data_imports/mk/data_imports.mk shotwell-0.11.92/src/data_imports/mk/data_imports.mk --- shotwell-0.11.91/src/data_imports/mk/data_imports.mk 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/data_imports/mk/data_imports.mk 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,31 @@ + +# UNIT_NAME is the Vala namespace. A file named UNIT_NAME.vala must be in this directory with +# a init() and terminate() function declared in the namespace. +UNIT_NAME := DataImports + +# UNIT_DIR should match the subdirectory the files are located in. Generally UNIT_NAME in all +# lowercase. The name of this file should be UNIT_DIR.mk. +UNIT_DIR := data_imports + +# All Vala files in the unit should be listed here with no subdirectory prefix. +# +# NOTE: Do *not* include the unit's master file, i.e. UNIT_NAME.vala. +UNIT_FILES := \ + DataImportsPluginHost.vala \ + DataImportsUI.vala \ + DataImportJob.vala \ + DataImportSource.vala + +# Any unit this unit relies upon (and should be initialized before it's initialized) should +# be listed here using its Vala namespace. +# +# NOTE: All units are assumed to rely upon the unit-unit. Do not include that here. +UNIT_USES := + +# List any additional files that are used in the build process as a part of this unit that should +# be packaged in the tarball. File names should be relative to the unit's home directory. +UNIT_RC := + +# unitize.mk must be called at the end of each UNIT_DIR.mk file. +include unitize.mk + diff -Nru shotwell-0.11.91/src/db/DatabaseTable.vala shotwell-0.11.92/src/db/DatabaseTable.vala --- shotwell-0.11.91/src/db/DatabaseTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/DatabaseTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -41,8 +41,8 @@ if (filename != Db.IN_MEMORY_NAME) { try { File file_db = File.new_for_path(filename); - FileInfo info = file_db.query_info(GLib.FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FileQueryInfoFlags.NONE); - if (!info.get_attribute_boolean(GLib.FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) + FileInfo info = file_db.query_info(FileAttribute.ACCESS_CAN_WRITE, FileQueryInfoFlags.NONE); + if (!info.get_attribute_boolean(FileAttribute.ACCESS_CAN_WRITE)) AppWindow.panic(_("Unable to write to photo database file:\n %s").printf(filename)); } catch (Error e) { AppWindow.panic(_("Error accessing database file:\n %s\n\nError was: \n%s").printf(filename, diff -Nru shotwell-0.11.91/src/db/Db.vala shotwell-0.11.92/src/db/Db.vala --- shotwell-0.11.91/src/db/Db.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/Db.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/EventTable.vala shotwell-0.11.92/src/db/EventTable.vala --- shotwell-0.11.91/src/db/EventTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/EventTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/FaceLocationTable.vala shotwell-0.11.92/src/db/FaceLocationTable.vala --- shotwell-0.11.91/src/db/FaceLocationTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/FaceLocationTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/FaceTable.vala shotwell-0.11.92/src/db/FaceTable.vala --- shotwell-0.11.91/src/db/FaceTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/FaceTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/PhotoTable.vala shotwell-0.11.92/src/db/PhotoTable.vala --- shotwell-0.11.91/src/db/PhotoTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/PhotoTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -1053,20 +1053,14 @@ if (filesize != info.get_size()) return false; - TimeVal modification; - info.get_modification_time(out modification); - - return timestamp == modification.tv_sec; + return timestamp == info.get_modification_time().tv_sec; } public bool is_touched(FileInfo info) { if (filesize != info.get_size()) return false; - TimeVal modification; - info.get_modification_time(out modification); - - return timestamp != modification.tv_sec; + return timestamp != info.get_modification_time().tv_sec; } // Copies another backing photo row into this one. diff -Nru shotwell-0.11.91/src/db/SavedSearchDBTable.vala shotwell-0.11.92/src/db/SavedSearchDBTable.vala --- shotwell-0.11.91/src/db/SavedSearchDBTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/SavedSearchDBTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/TagTable.vala shotwell-0.11.92/src/db/TagTable.vala --- shotwell-0.11.91/src/db/TagTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/TagTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/TombstoneTable.vala shotwell-0.11.92/src/db/TombstoneTable.vala --- shotwell-0.11.91/src/db/TombstoneTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/TombstoneTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/VersionTable.vala shotwell-0.11.92/src/db/VersionTable.vala --- shotwell-0.11.91/src/db/VersionTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/VersionTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/db/VideoTable.vala shotwell-0.11.92/src/db/VideoTable.vala --- shotwell-0.11.91/src/db/VideoTable.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/db/VideoTable.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Debug.vala shotwell-0.11.92/src/Debug.vala --- shotwell-0.11.91/src/Debug.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Debug.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/DesktopIntegration.vala shotwell-0.11.92/src/DesktopIntegration.vala --- shotwell-0.11.91/src/DesktopIntegration.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/DesktopIntegration.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Dialogs.vala shotwell-0.11.92/src/Dialogs.vala --- shotwell-0.11.91/src/Dialogs.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Dialogs.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -49,15 +49,6 @@ namespace ExportUI { private static File current_export_dir = null; -// Dummy function for suppressing 'could not stat file' errors -// generated when saving into a previously non-existant file - -// please see https://bugzilla.gnome.org/show_bug.cgi?id=662814 -// This should be removed once GTK 3.4 is widely available, as -// it is slated to correct the problem. -public void suppress_warnings(string? log_domain, LogLevelFlags log_levels, string message) { - // do nothing. -} - public File? choose_file(string current_file_basename) { if (current_export_dir == null) current_export_dir = File.new_for_path(Environment.get_home_dir()); @@ -435,7 +426,7 @@ ok_button.sensitive = (pixels_entry.get_text_length() > 0) && (int.parse(pixels_entry.get_text()) > 0); } - private void on_pixels_insert_text(string text, int length, void *position) { + private void on_pixels_insert_text(string text, int length, ref int position) { // This is necessary because SignalHandler.block_by_func() is not properly bound if (in_insert) return; @@ -454,7 +445,7 @@ } if (new_text.length > 0) - pixels_entry.insert_text(new_text, (int) new_text.length, position); + pixels_entry.insert_text(new_text, (int) new_text.length, ref position); Signal.stop_emission_by_name(pixels_entry, "insert-text"); @@ -1621,7 +1612,7 @@ Gee.Collection terminal_tags = Tag.get_terminal_tags(source_tags); Gee.SortedSet tag_basenames = new Gee.TreeSet(); - foreach (Tag tag in terminal_tags) + foreach (Tag tag in terminal_tags) tag_basenames.add(HierarchicalTagUtilities.get_basename(tag.get_path())); string? text = null; @@ -1665,13 +1656,27 @@ } +public interface WelcomeServiceEntry : GLib.Object { + public abstract string get_service_name(); + + public abstract void execute(); +} + public class WelcomeDialog : Gtk.Dialog { Gtk.CheckButton hide_button; - Gtk.CheckButton? fspot_import_check = null; Gtk.CheckButton? system_pictures_import_check = null; - + Gtk.CheckButton[] external_import_checks = new Gtk.CheckButton[0]; + WelcomeServiceEntry[] external_import_entries = new WelcomeServiceEntry[0]; + Gtk.Label secondary_text; + Gtk.Label instruction_header; + Gtk.VBox import_content; + Gtk.VBox import_action_checkbox_packer; + Gtk.VBox external_import_action_checkbox_packer; + Spit.DataImports.WelcomeImportMetaHost import_meta_host; + bool import_content_already_installed = false; + public WelcomeDialog(Gtk.Window owner) { - bool show_fspot_import = is_fspot_import_possible(); + import_meta_host = new Spit.DataImports.WelcomeImportMetaHost(this); bool show_system_pictures_import = is_system_pictures_import_possible(); Gtk.Widget ok_button = add_button(Gtk.Stock.OK, Gtk.ResponseType.OK); set_title(_("Welcome!")); @@ -1683,30 +1688,22 @@ primary_text.set_markup( "%s".printf(_("Welcome to Shotwell!"))); primary_text.set_alignment(0, 0.5f); - Gtk.Label secondary_text = new Gtk.Label(""); - if (!(show_fspot_import || show_system_pictures_import)) { - secondary_text.set_markup("%s".printf( - _("To get started, import photos in any of these ways:"))); - } + secondary_text = new Gtk.Label(""); + secondary_text.set_markup("%s".printf( + _("To get started, import photos in any of these ways:"))); secondary_text.set_alignment(0, 0.5f); Gtk.Image image = new Gtk.Image.from_pixbuf(Resources.get_icon(Resources.ICON_APP, 50)); - Gtk.Widget? header_text = null; - if (show_fspot_import || show_system_pictures_import) { - header_text = primary_text; - } else { - header_text = new Gtk.VBox(false, 0); - - ((Gtk.VBox) header_text).pack_start(primary_text, false, false, 5); - ((Gtk.VBox) header_text).pack_start(secondary_text, false, false, 0); - } + Gtk.VBox header_text = new Gtk.VBox(false, 0); + header_text.pack_start(primary_text, false, false, 5); + header_text.pack_start(secondary_text, false, false, 0); Gtk.HBox header_content = new Gtk.HBox(false, 12); header_content.pack_start(image, false, false, 0); header_content.pack_start(header_text, false, false, 0); Gtk.Label instructions = new Gtk.Label(""); - string indent_prefix = (show_fspot_import || show_system_pictures_import) ? " " : ""; + string indent_prefix = " "; // we can't tell what the indent prefix is going to be so assume we need one instructions.set_markup(((indent_prefix + "• %s\n") + (indent_prefix + "• %s\n") + (indent_prefix + "• %s")).printf( _("Choose File %s Import From Folder").printf("▸"), @@ -1714,39 +1711,30 @@ _("Connect a camera to your computer and import"))); instructions.set_alignment(0, 0.5f); - Gtk.VBox? import_action_checkbox_packer = null; - if (show_fspot_import || show_system_pictures_import) { - import_action_checkbox_packer = new Gtk.VBox(false, 2); - - if (show_fspot_import) { - fspot_import_check = new Gtk.CheckButton.with_mnemonic( - _("Import photos from your _F-Spot library")); - import_action_checkbox_packer.add(fspot_import_check); - fspot_import_check.set_active(true); - } - - if (show_system_pictures_import) { - system_pictures_import_check = new Gtk.CheckButton.with_mnemonic( - _("_Import photos from your %s folder").printf( - get_display_pathname(AppDirs.get_import_dir()))); - import_action_checkbox_packer.add(system_pictures_import_check); - system_pictures_import_check.set_active(true); - } - } + import_action_checkbox_packer = new Gtk.VBox(false, 2); - Gtk.Label? instruction_header = null; - if (show_fspot_import || show_system_pictures_import) { - instruction_header = new Gtk.Label( - _("You can also import photos in any of these ways:")); - instruction_header.set_alignment(0.0f, 0.5f); - } + external_import_action_checkbox_packer = new Gtk.VBox(false, 2); + import_action_checkbox_packer.add(external_import_action_checkbox_packer); + + if (show_system_pictures_import) { + system_pictures_import_check = new Gtk.CheckButton.with_mnemonic( + _("_Import photos from your %s folder").printf( + get_display_pathname(AppDirs.get_import_dir()))); + import_action_checkbox_packer.add(system_pictures_import_check); + system_pictures_import_check.set_active(true); + } + + instruction_header = new Gtk.Label( + _("You can also import photos in any of these ways:")); + instruction_header.set_alignment(0.0f, 0.5f); + instruction_header.set_margin_top(20); Gtk.VBox content = new Gtk.VBox(false, 16); content.pack_start(header_content, true, true, 0); - if (show_fspot_import || show_system_pictures_import) { - content.add(import_action_checkbox_packer); - content.add(instruction_header); - } + import_content = new Gtk.VBox(false, 2); + content.add(import_content); + //content.add(import_action_checkbox_packer); + //content.add(instruction_header); content.pack_start(instructions, false, false, 0); hide_button = new Gtk.CheckButton.with_mnemonic(_("_Don't show this message again")); @@ -1759,12 +1747,39 @@ ((Gtk.Box) get_content_area()).pack_start(alignment, false, false, 0); - set_has_resize_grip(false); + set_has_resize_grip(false); ok_button.grab_focus(); + + install_import_content(); + + import_meta_host.start(); + } + + private void install_import_content() { + if ( + (external_import_checks.length > 0 || system_pictures_import_check != null) && + (import_content_already_installed == false) + ) { + secondary_text.set_markup(""); + import_content.add(import_action_checkbox_packer); + import_content.add(instruction_header); + import_content_already_installed = true; + } + } + + public void install_service_entry(WelcomeServiceEntry entry) { + debug("WelcomeDialog: Installing service entry for %s".printf(entry.get_service_name())); + external_import_entries += entry; + Gtk.CheckButton entry_check = new Gtk.CheckButton.with_label( + _("Import photos from your %s library").printf(entry.get_service_name())); + external_import_checks += entry_check; + entry_check.set_active(true); + external_import_action_checkbox_packer.add(entry_check); + install_import_content(); } - public bool execute(out bool do_fspot_import, out bool do_system_pictures_import) { + public bool execute(out WelcomeServiceEntry[] selected_import_entries, out bool do_system_pictures_import) { show_all(); bool ok = (run() == Gtk.ResponseType.OK); @@ -1773,7 +1788,13 @@ if (ok) show_dialog = !hide_button.get_active(); - do_fspot_import = (fspot_import_check != null) ? fspot_import_check.get_active() : false; + // Use a temporary variable as += cannot be used on parameters + WelcomeServiceEntry[] result = new WelcomeServiceEntry[0]; + for (int i = 0; i < external_import_entries.length; i++) { + if (external_import_checks[i].get_active() == true) + result += external_import_entries[i]; + } + selected_import_entries = result; do_system_pictures_import = (system_pictures_import_check != null) ? system_pictures_import_check.get_active() : false; @@ -1798,10 +1819,6 @@ return false; } } - - private static bool is_fspot_import_possible() { - return AlienDb.FSpot.FSpotDatabaseDriver.is_available(); - } } public class PreferencesDialog { @@ -2089,7 +2106,8 @@ } private void on_value_changed() { - set_background_color(bg_color_adjustment.get_upper() - bg_color_adjustment.get_value()); + set_background_color((double)(bg_color_adjustment.get_upper() - + bg_color_adjustment.get_value()) / 65535.0); } private bool on_bg_color_reset(Gdk.EventButton event) { @@ -2148,15 +2166,16 @@ } private void set_background_color(double bg_color_value) { - Config.Facade.get_instance().set_bg_color(to_grayscale((uint16) bg_color_value)); + Config.Facade.get_instance().set_bg_color(to_grayscale(bg_color_value)); } - private Gdk.Color to_grayscale(uint16 color_value) { - Gdk.Color color = Gdk.Color(); + private Gdk.RGBA to_grayscale(double color_value) { + Gdk.RGBA color = Gdk.RGBA(); color.red = color_value; color.green = color_value; color.blue = color_value; + color.alpha = 1.0; return color; } diff -Nru shotwell-0.11.91/src/Dimensions.vala shotwell-0.11.92/src/Dimensions.vala --- shotwell-0.11.91/src/Dimensions.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Dimensions.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -101,13 +101,13 @@ } public Dimensions with_min(int min_width, int min_height) { - Dimensions min = Dimensions(); - min.width = (width > min_width) ? width : min_width; - min.height = (height > min_height) ? height : min_height; - - return min; + return Dimensions(int.max(width, min_width), int.max(height, min_height)); } + public Dimensions with_max(int max_width, int max_height) { + return Dimensions(int.min(width, max_width), int.min(height, max_height)); + } + public Dimensions get_scaled(int scale, bool scale_up) { assert(scale > 0); @@ -559,7 +559,7 @@ int zoomed_width = get_zoomed_width(); int zoomed_height = get_zoomed_height(); - Gdk.Rectangle result = {0}; + Gdk.Rectangle result = Gdk.Rectangle(); if (viewport_dimensions.width < zoomed_width) { result.x = viewport_center.x - (viewport_dimensions.width / 2); @@ -598,7 +598,7 @@ public Gdk.Rectangle get_viewing_rectangle_wrt_screen() { Gdk.Rectangle wrt_content = get_viewing_rectangle_wrt_content(); - Gdk.Rectangle result = {0}; + Gdk.Rectangle result = Gdk.Rectangle(); result.x = (viewport_dimensions.width / 2) - (wrt_content.width / 2); if (result.x < 0) result.x = 0; @@ -622,7 +622,7 @@ Gdk.Rectangle viewing_rectangle = get_viewing_rectangle_wrt_content(); - Gdk.Rectangle result = {0}; + Gdk.Rectangle result = Gdk.Rectangle(); result.x = (int) (viewing_rectangle.x * scale); result.x = result.x.clamp(0, for_pixbuf.width); result.y = (int) (viewing_rectangle.y * scale); diff -Nru shotwell-0.11.91/src/direct/DirectPhotoPage.vala shotwell-0.11.92/src/direct/DirectPhotoPage.vala --- shotwell-0.11.91/src/direct/DirectPhotoPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/direct/DirectPhotoPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -129,6 +129,12 @@ crop.tooltip = Resources.CROP_TOOLTIP; actions += crop; + Gtk.ActionEntry straighten = { "Straighten", Gtk.Stock.REFRESH, TRANSLATABLE, "A", + TRANSLATABLE, toggle_straighten }; + straighten.label = Resources.STRAIGHTEN_MENU; + straighten.tooltip = Resources.STRAIGHTEN_TOOLTIP; + actions += straighten; + Gtk.ActionEntry red_eye = { "RedEye", Resources.REDEYE, TRANSLATABLE, "Y", TRANSLATABLE, toggle_redeye }; red_eye.label = Resources.RED_EYE_MENU; @@ -331,6 +337,7 @@ set_action_sensitive("FlipVertically", sensitivity); set_action_sensitive("Enhance", sensitivity); set_action_sensitive("Crop", sensitivity); + set_action_sensitive("Straighten", sensitivity); set_action_sensitive("RedEye", sensitivity); set_action_sensitive("Adjust", sensitivity); set_action_sensitive("Revert", sensitivity); diff -Nru shotwell-0.11.91/src/direct/DirectPhoto.vala shotwell-0.11.92/src/direct/DirectPhoto.vala --- shotwell-0.11.91/src/direct/DirectPhoto.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/direct/DirectPhoto.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -31,8 +31,9 @@ // Gets the dimensions of this photo's pixbuf when scaled to original // size and saves them where get_raw_dimensions can find them. private void save_dims() { - try { - backing_photo_row.dim = Dimensions.for_pixbuf(get_pixbuf(Scaling.for_original())); + try { + backing_photo_row.dim = Dimensions.for_pixbuf(get_pixbuf_with_options(Scaling.for_original(), + Exception.CROP | Exception.STRAIGHTEN | Exception.ORIENTATION)); } catch (Error e) { warning("Dimensions for image %s could not be gotten.", to_string()); } diff -Nru shotwell-0.11.91/src/direct/Direct.vala shotwell-0.11.92/src/direct/Direct.vala --- shotwell-0.11.91/src/direct/Direct.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/direct/Direct.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/direct/DirectView.vala shotwell-0.11.92/src/direct/DirectView.vala --- shotwell-0.11.91/src/direct/DirectView.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/direct/DirectView.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/direct/DirectWindow.vala shotwell-0.11.92/src/direct/DirectWindow.vala --- shotwell-0.11.91/src/direct/DirectWindow.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/direct/DirectWindow.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/DirectoryMonitor.vala shotwell-0.11.92/src/DirectoryMonitor.vala --- shotwell-0.11.91/src/DirectoryMonitor.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/DirectoryMonitor.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -256,7 +256,7 @@ // This *only* retrieves the file ID, which is then used to obtain the in-memory file // information. try { - info = file.query_info(FILE_ATTRIBUTE_ID_FILE, UNKNOWN_INFO_FLAGS, cancellable); + info = file.query_info(FileAttribute.ID_FILE, UNKNOWN_INFO_FLAGS, cancellable); } catch (Error err) { warning("Unable to query file ID of %s: %s", file.get_path(), err.message); @@ -266,7 +266,7 @@ if (!is_file_symlink_supported(info)) return null; - string? id = info.get_attribute_string(FILE_ATTRIBUTE_ID_FILE); + string? id = info.get_attribute_string(FileAttribute.ID_FILE); if (id == null) return null; @@ -284,8 +284,7 @@ // get all the interesting matchable items from the supplied FileInfo int64 match_size = match.get_size(); - TimeVal match_time; - match.get_modification_time(out match_time); + TimeVal match_time = match.get_modification_time(); foreach (File file in map.keys) { FileInfo info = map.get(file); @@ -298,8 +297,7 @@ if (match_size != info.get_size()) continue; - TimeVal time; - info.get_modification_time(out time); + TimeVal time = info.get_modification_time(); if (time.tv_sec != match_time.tv_sec) continue; diff -Nru shotwell-0.11.91/src/editing_tools/EditingTools.vala shotwell-0.11.92/src/editing_tools/EditingTools.vala --- shotwell-0.11.91/src/editing_tools/EditingTools.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/editing_tools/EditingTools.vala 2012-02-21 01:04:19.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -53,6 +53,12 @@ set_accept_focus(true); set_can_focus(true); set_has_resize_grip(false); + + Log.set_handler("Gdk", LogLevelFlags.LEVEL_WARNING, suppress_warnings); + } + + ~EditingToolWindow() { + Log.set_handler("Gdk", LogLevelFlags.LEVEL_WARNING, Log.default_handler); } public override void add(Gtk.Widget widget) { @@ -64,7 +70,10 @@ } public override bool key_press_event(Gdk.EventKey event) { - return AppWindow.get_instance().key_press_event(event); + if (base.key_press_event(event)) { + return true; + } + return AppWindow.get_instance().key_press_event(event); } public override bool button_press_event(Gdk.EventButton event) { @@ -80,7 +89,7 @@ public override void realize() { set_opacity(Resources.TRANSIENT_WINDOW_OPACITY); - + base.realize(); } } @@ -115,6 +124,10 @@ public signal void resized_scaled_pixbuf(Dimensions old_dim, Gdk.Pixbuf scaled, Gdk.Rectangle scaled_position); + public Gdk.Rectangle unscaled_to_raw_rect(Gdk.Rectangle rectangle) { + return photo.unscaled_to_raw_rect(rectangle); + } + public Gdk.Point active_to_unscaled_point(Gdk.Point active_point) { Gdk.Rectangle scaled_position = get_scaled_pixbuf_position(); Dimensions unscaled_dims = photo.get_dimensions(); @@ -142,7 +155,7 @@ upper_left = active_to_unscaled_point(upper_left); lower_right = active_to_unscaled_point(lower_right); - Gdk.Rectangle unscaled_rect = {0}; + Gdk.Rectangle unscaled_rect = Gdk.Rectangle(); unscaled_rect.x = upper_left.x; unscaled_rect.y = upper_left.y; unscaled_rect.width = lower_right.x - upper_left.x; @@ -172,7 +185,7 @@ upper_left = user_to_active_point(upper_left); lower_right = user_to_active_point(lower_right); - Gdk.Rectangle active_rect = {0}; + Gdk.Rectangle active_rect = Gdk.Rectangle(); active_rect.x = upper_left.x; active_rect.y = upper_left.y; active_rect.width = lower_right.x - upper_left.x; @@ -244,7 +257,7 @@ default_ctx.save(); // paint black background - Gdk.cairo_set_source_color(default_ctx, container.style.black); + set_source_color_from_string(default_ctx, "#000"); default_ctx.rectangle(0, 0, surface_dim.width, surface_dim.height); default_ctx.fill(); @@ -259,7 +272,7 @@ public void paint_pixbuf_area(Gdk.Pixbuf pixbuf, Box source_area) { default_ctx.save(); if (pixbuf.get_has_alpha()) { - Gdk.cairo_set_source_color(default_ctx, container.style.black); + set_source_color_from_string(default_ctx, "#000"); default_ctx.rectangle(scaled_position.x + source_area.left, scaled_position.y + source_area.top, source_area.get_width(), source_area.get_height()); @@ -320,18 +333,44 @@ ctx.stroke(); } - public void draw_horizontal_line(Cairo.Context ctx, int x, int y, int width) { - x += scaled_position.x; - y += scaled_position.y; + /** + * Draw a horizontal line into the specified Cairo context at the specified position, taking + * into account the scaled position of the image unless directed otherwise. + * + * @param ctx The drawing context of the surface we're drawing to. + * @param x The horizontal position to place the line at. + * @param y The vertical position to place the line at. + * @param width The length of the line. + * @param use_scaled_pos Whether to use absolute window positioning or take into account the + * position of the scaled image. + */ + public void draw_horizontal_line(Cairo.Context ctx, int x, int y, int width, bool use_scaled_pos = true) { + if (use_scaled_pos) { + x += scaled_position.x; + y += scaled_position.y; + } ctx.move_to(x + 0.5, y + 0.5); ctx.line_to(x + width - 1, y + 0.5); ctx.stroke(); } - public void draw_vertical_line(Cairo.Context ctx, int x, int y, int height) { - x += scaled_position.x; - y += scaled_position.y; + /** + * Draw a vertical line into the specified Cairo context at the specified position, taking + * into account the scaled position of the image unless directed otherwise. + * + * @param ctx The drawing context of the surface we're drawing to. + * @param x The horizontal position to place the line at. + * @param y The vertical position to place the line at. + * @param width The length of the line. + * @param use_scaled_pos Whether to use absolute window positioning or take into account the + * position of the scaled image. + */ + public void draw_vertical_line(Cairo.Context ctx, int x, int y, int height, bool use_scaled_pos = true) { + if (use_scaled_pos) { + x += scaled_position.x; + y += scaled_position.y; + } ctx.move_to(x + 0.5, y + 0.5); ctx.line_to(x + 0.5, y + height - 1); @@ -801,15 +840,15 @@ return false; } - private void on_width_insert_text(string text, int length, void *position) { - on_entry_insert_text(crop_tool_window.custom_width_entry, text, length, position); + private void on_width_insert_text(string text, int length, ref int position) { + on_entry_insert_text(crop_tool_window.custom_width_entry, text, length, ref position); } - private void on_height_insert_text(string text, int length, void *position) { - on_entry_insert_text(crop_tool_window.custom_height_entry, text, length, position); + private void on_height_insert_text(string text, int length, ref int position) { + on_entry_insert_text(crop_tool_window.custom_height_entry, text, length, ref position); } - private void on_entry_insert_text(Gtk.Entry sender, string text, int length, void *position) { + private void on_entry_insert_text(Gtk.Entry sender, string text, int length, ref int position) { if (entry_insert_in_progress) return; @@ -827,7 +866,7 @@ } if (new_text.length > 0) - sender.insert_text(new_text, (int) new_text.length, position); + sender.insert_text(new_text, (int) new_text.length, ref position); Signal.stop_emission_by_name(sender, "insert-text"); @@ -961,57 +1000,24 @@ if (user_aspect_ratio == ANY_ASPECT_RATIO) return crop; - float scaled_width = (float) crop.get_width(); - float scaled_height = (float) crop.get_height(); - float scaled_center_x = ((float) crop.left) + (scaled_width / 2.0f); - float scaled_center_y = ((float) crop.top) + (scaled_height / 2.0f); - float scaled_aspect_ratio = scaled_width / scaled_height; - - // Crop positioning in the presence of constraint is a three-phase process - - // PHASE 1: Naively rescale the width and the height of the box so that it has the - // user-specified aspect ratio. Even in this initial transformation, the - // box's center and minor axis length are preserved. Preserving the center - // is especially important since this way the subject that the user has framed - // within the crop reticle is preserved. - if (scaled_aspect_ratio > 1.0f) - scaled_width = scaled_height; - else - scaled_height = scaled_width; - scaled_width *= user_aspect_ratio; - - // PHASE 2: Now that the box has the correct aspect ratio, grow it or shrink it such - // that it has the same area that it had prior to constraint. This prevents - // the box from growing or shrinking erratically as constraints are set and - // unset. + // PHASE 1: Scale to the desired aspect ratio, preserving area and center. float old_area = (float) (crop.get_width() * crop.get_height()); - float new_area = scaled_width * scaled_height; - float area_correct_factor = (float) Math.sqrt(old_area / new_area); - scaled_width *= area_correct_factor; - scaled_height *= area_correct_factor; - - // PHASE 3: The new crop box may have edges that fall outside of the boundaries of - // the photo. Here, we rescale it such that it fits within the boundaries - // of the photo. - int photo_right_edge = canvas.get_scaled_pixbuf_position().width - 1; - int photo_bottom_edge = canvas.get_scaled_pixbuf_position().height - 1; - - int new_box_left = (int) ((scaled_center_x - (scaled_width / 2.0f))); - int new_box_right = (int) ((scaled_center_x + (scaled_width / 2.0f))); - int new_box_top = (int) ((scaled_center_y - (scaled_height / 2.0f))); - int new_box_bottom = (int) ((scaled_center_y + (scaled_height / 2.0f))); - - if(new_box_left < 0) new_box_left = 0; - if(new_box_top < 0) new_box_top = 0; - if(new_box_right > photo_right_edge) new_box_right = photo_right_edge; - if(new_box_bottom > photo_bottom_edge) new_box_bottom = photo_bottom_edge; - - Box new_crop_box = Box((int) (new_box_left), - (int) (new_box_top), - (int) (new_box_right), - (int) (new_box_bottom)); - - return new_crop_box; + crop.adjust_height((int) Math.sqrt(old_area / user_aspect_ratio)); + crop.adjust_width((int) Math.sqrt(old_area * user_aspect_ratio)); + + // PHASE 2: Crop to the image boundary. + Dimensions image_size = get_photo_dimensions(); + double angle; + canvas.get_photo().get_straighten(out angle); + crop = clamp_inside_rotated_image(crop, image_size.width, image_size.height, angle, false); + + // PHASE 3: Crop down to the aspect ratio if necessary. + if (crop.get_width() >= crop.get_height() * user_aspect_ratio) // possibly too wide + crop.adjust_width((int) (crop.get_height() * user_aspect_ratio)); + else // possibly too tall + crop.adjust_height((int) (crop.get_width() / user_aspect_ratio)); + + return crop; } public override void activate(PhotoCanvas canvas) { @@ -1035,8 +1041,10 @@ // set up the constraint combo box crop_tool_window.constraint_combo.set_model(constraint_list); - crop_tool_window.constraint_combo.set_active(Config.Facade.get_instance().get_last_crop_menu_choice()); - + if(!canvas.get_photo().has_crop()) { + crop_tool_window.constraint_combo.set_active(Config.Facade.get_instance().get_last_crop_menu_choice()); + } + // set up the pivot reticle button update_pivot_button_state(); reticle_orientation = ReticleOrientation.LANDSCAPE; @@ -1044,7 +1052,7 @@ bind_window_handlers(); // obtain crop dimensions and paint against the uncropped photo - Dimensions uncropped_dim = canvas.get_photo().get_original_dimensions(); + Dimensions uncropped_dim = canvas.get_photo().get_dimensions(Photo.Exception.CROP); Box crop; if (!canvas.get_photo().get_crop(out crop)) { @@ -1080,10 +1088,12 @@ crop_tool_window.hide(); // was 'custom' the most-recently-chosen menu item? - if (constraints[Config.Facade.get_instance().get_last_crop_menu_choice()].aspect_ratio == - CUSTOM_ASPECT_RATIO) { - // yes, switch to custom mode, make the entry fields appear. - set_custom_constraint_mode(); + if(!canvas.get_photo().has_crop()) { + if (constraints[Config.Facade.get_instance().get_last_crop_menu_choice()].aspect_ratio == + CUSTOM_ASPECT_RATIO) { + // yes, switch to custom mode, make the entry fields appear. + set_custom_constraint_mode(); + } } // since we no longer just run with the default, but rather @@ -1189,36 +1199,28 @@ public override Gdk.Pixbuf? get_display_pixbuf(Scaling scaling, Photo photo, out Dimensions max_dim) throws Error { - // show the uncropped photo for editing, but return null if no crop so the current pixbuf - // is used - if (!photo.has_crop()) { - max_dim = Dimensions(); - - return null; - } - - max_dim = photo.get_original_dimensions(); + max_dim = photo.get_dimensions(Photo.Exception.CROP); return photo.get_pixbuf_with_options(scaling, Photo.Exception.CROP); } private void prepare_ctx(Cairo.Context ctx, Dimensions dim) { wide_black_ctx = new Cairo.Context(ctx.get_target()); - Gdk.cairo_set_source_color(wide_black_ctx, fetch_color("#000")); + set_source_color_from_string(wide_black_ctx, "#000"); wide_black_ctx.set_line_width(1); wide_white_ctx = new Cairo.Context(ctx.get_target()); - Gdk.cairo_set_source_color(wide_white_ctx, fetch_color("#FFF")); + set_source_color_from_string(wide_white_ctx, "#FFF"); wide_white_ctx.set_line_width(1); thin_white_ctx = new Cairo.Context(ctx.get_target()); - Gdk.cairo_set_source_color(thin_white_ctx, fetch_color("#FFF")); + set_source_color_from_string(thin_white_ctx, "#FFF"); thin_white_ctx.set_line_width(0.5); } private void on_resized_pixbuf(Dimensions old_dim, Gdk.Pixbuf scaled, Gdk.Rectangle scaled_position) { Dimensions new_dim = Dimensions.for_pixbuf(scaled); - Dimensions uncropped_dim = canvas.get_photo().get_original_dimensions(); + Dimensions uncropped_dim = canvas.get_photo().get_dimensions(Photo.Exception.CROP); // rescale to full crop Box crop = scaled_crop.get_scaled_similar(old_dim, uncropped_dim); @@ -1313,7 +1315,7 @@ // scale screen-coordinate crop to photo's coordinate system Box crop = scaled_crop.get_scaled_similar( Dimensions.for_rectangle(canvas.get_scaled_pixbuf_position()), - canvas.get_photo().get_original_dimensions()); + canvas.get_photo().get_dimensions(Photo.Exception.CROP)); // crop the current pixbuf and offer it to the editing host Gdk.Pixbuf cropped = new Gdk.Pixbuf.subpixbuf(canvas.get_scaled_pixbuf(), scaled_crop.left, @@ -1380,13 +1382,6 @@ } } - private void revert_crop(out int left, out int top, out int right, out int bottom) { - left = scaled_crop.left; - top = scaled_crop.top; - right = scaled_crop.right; - bottom = scaled_crop.bottom; - } - private int eval_radial_line(double center_x, double center_y, double bounds_x, double bounds_y, double user_x) { double decision_slope = (bounds_y - center_y) / (bounds_x - center_x); @@ -1395,6 +1390,21 @@ return (int) (decision_slope * user_x + decision_intercept); } + // Return the dimensions of the uncropped source photo scaled to canvas coordinates. + private Dimensions get_photo_dimensions() { + Dimensions photo_dims = canvas.get_photo().get_dimensions(Photo.Exception.CROP); + Dimensions surface_dims = canvas.get_surface_dim(); + double scale_factor = double.min((double) surface_dims.width / photo_dims.width, + (double) surface_dims.height / photo_dims.height); + scale_factor = double.min(scale_factor, 1.0); + + photo_dims = canvas.get_photo().get_dimensions( + Photo.Exception.CROP | Photo.Exception.STRAIGHTEN); + + return { (int) (photo_dims.width * scale_factor), + (int) (photo_dims.height * scale_factor) }; + } + private bool on_canvas_manipulation(int x, int y) { Gdk.Rectangle scaled_pos = canvas.get_scaled_pixbuf_position(); @@ -1420,8 +1430,6 @@ int bottom = scaled_crop.bottom; // get extra geometric information needed to enforce constraints - int photo_right_edge = canvas.get_scaled_pixbuf().width - 1; - int photo_bottom_edge = canvas.get_scaled_pixbuf().height - 1; int center_x = (left + right) / 2; int center_y = (top + bottom) / 2; @@ -1590,16 +1598,13 @@ // constraint). int width = right - left + 1; int height = bottom - top + 1; - if (get_constraint_aspect_ratio() == ANY_ASPECT_RATIO) { - if (left < 0) - left = 0; - if (top < 0) - top = 0; - if (right > photo_right_edge) - right = photo_right_edge; - if (bottom > photo_bottom_edge) - bottom = photo_bottom_edge; + Dimensions photo_dims = get_photo_dimensions(); + double angle; + canvas.get_photo().get_straighten(out angle); + + Box new_crop; + if (get_constraint_aspect_ratio() == ANY_ASPECT_RATIO) { width = right - left + 1; height = bottom - top + 1; @@ -1640,16 +1645,29 @@ default: break; } + + // preliminary crop region has been chosen, now clamp it inside the + // image as needed. + + new_crop = clamp_inside_rotated_image( + Box(left, top, right, bottom), + photo_dims.width, photo_dims.height, angle, + in_manipulation == BoxLocation.INSIDE); + } else { - if ((left < 0) || (top < 0) || (right > photo_right_edge) || - (bottom > photo_bottom_edge) || (width < CROP_MIN_SIZE) || - (height < CROP_MIN_SIZE)) { - revert_crop(out left, out top, out right, out bottom); + // one of the constrained modes is active; revert instead of clamping so + // that aspect ratio stays intact + + new_crop = Box(left, top, right, bottom); + Box adjusted = clamp_inside_rotated_image(new_crop, + photo_dims.width, photo_dims.height, angle, + in_manipulation == BoxLocation.INSIDE); + + if (adjusted != new_crop || width < CROP_MIN_SIZE || height < CROP_MIN_SIZE) { + new_crop = scaled_crop; // revert crop move } } - Box new_crop = Box(left, top, right, bottom); - if (in_manipulation != BoxLocation.INSIDE) crop_resized(new_crop); else @@ -1707,31 +1725,9 @@ erase_crop_tool(scaled_crop); canvas.invalidate_area(scaled_crop); - Box scaled_horizontal; - Box scaled_vertical; - Box new_horizontal; - Box new_vertical; - BoxComplements complements = scaled_crop.shifted_complements(new_crop, out scaled_horizontal, - out scaled_vertical, out new_horizontal, out new_vertical); - - if (complements == BoxComplements.HORIZONTAL || complements == BoxComplements.BOTH) { - // paint in the horizontal complements appropriately - set_area_alpha(scaled_horizontal, 0.5); - set_area_alpha(new_horizontal, 0.0); - } - - if (complements == BoxComplements.VERTICAL || complements == BoxComplements.BOTH) { - // paint in vertical complements appropriately - set_area_alpha(scaled_vertical, 0.5); - set_area_alpha(new_vertical, 0.0); - } - - if (complements == BoxComplements.NONE) { - // this means the two boxes have no intersection, not that they're equal ... since - // there's no intersection, fill in both new and old with apropriate pixbufs - set_area_alpha(scaled_crop, 0.5); - set_area_alpha(new_crop, 0.0); - } + set_area_alpha(scaled_crop, 0.5); + set_area_alpha(new_crop, 0.0); + // paint crop in new location paint_crop_tool(new_crop); @@ -2436,7 +2432,7 @@ } public static Gdk.Rectangle to_bounds_rect(EditingTools.RedeyeInstance inst) { - Gdk.Rectangle result = {0}; + Gdk.Rectangle result = Gdk.Rectangle(); result.x = inst.center.x - inst.radius; result.y = inst.center.y - inst.radius; result.width = 2 * inst.radius; @@ -2534,11 +2530,11 @@ private void prepare_ctx(Cairo.Context ctx, Dimensions dim) { wider_gray_ctx = new Cairo.Context(ctx.get_target()); - Gdk.cairo_set_source_color(wider_gray_ctx, fetch_color("#111")); + set_source_color_from_string(wider_gray_ctx, "#111"); wider_gray_ctx.set_line_width(3); thin_white_ctx = new Cairo.Context(ctx.get_target()); - Gdk.cairo_set_source_color(thin_white_ctx, fetch_color("#FFF")); + set_source_color_from_string(thin_white_ctx, "#FFF"); thin_white_ctx.set_line_width(1); } @@ -2566,22 +2562,25 @@ canvas.user_to_active_rect(bounds_rect_user); Gdk.Rectangle bounds_rect_unscaled = canvas.active_to_unscaled_rect(bounds_rect_active); + Gdk.Rectangle bounds_rect_raw = + canvas.unscaled_to_raw_rect(bounds_rect_unscaled); - RedeyeInstance instance_unscaled = - RedeyeInstance.from_bounds_rect(bounds_rect_unscaled); + RedeyeInstance instance_raw = + RedeyeInstance.from_bounds_rect(bounds_rect_raw); // transform screen coords back to image coords, // taking into account straightening angle. - int img_w = canvas.get_photo().get_master_dimensions().width; - int img_h = canvas.get_photo().get_master_dimensions().height; + Dimensions dimensions = canvas.get_photo().get_dimensions( + Photo.Exception.STRAIGHTEN | Photo.Exception.CROP); double theta = 0.0; canvas.get_photo().get_straighten(out theta); - instance_unscaled.center = rotate_point_arb(instance_unscaled.center, img_w, img_h, theta); + instance_raw.center = derotate_point_arb(instance_raw.center, + dimensions.width, dimensions.height, theta); - RedeyeCommand command = new RedeyeCommand(canvas.get_photo(), instance_unscaled, + RedeyeCommand command = new RedeyeCommand(canvas.get_photo(), instance_raw, Resources.RED_EYE_LABEL, Resources.RED_EYE_TOOLTIP); AppWindow.get_command_manager().execute(command); } diff -Nru shotwell-0.11.91/src/editing_tools/mk/editing_tools.mk shotwell-0.11.92/src/editing_tools/mk/editing_tools.mk --- shotwell-0.11.91/src/editing_tools/mk/editing_tools.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/editing_tools/mk/editing_tools.mk 2012-02-20 20:47:27.000000000 +0000 @@ -10,7 +10,8 @@ # All Vala files in the unit should be listed here with no subdirectory prefix. # # NOTE: Do *not* include the unit's master file, i.e. UNIT_NAME.vala. -UNIT_FILES := +UNIT_FILES := \ + StraightenTool.vala # Any unit this unit relies upon (and should be initialized before it's initialized) should # be listed here using its Vala namespace. diff -Nru shotwell-0.11.91/src/editing_tools/StraightenTool.vala shotwell-0.11.92/src/editing_tools/StraightenTool.vala --- shotwell-0.11.91/src/editing_tools/StraightenTool.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/editing_tools/StraightenTool.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,425 @@ + +/* Copyright 2009-2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +namespace EditingTools { + +/** + * An editing tool that allows one to introduce or remove a Dutch angle from + * a photograph. + */ +public class StraightenTool : EditingTool { + private const double MIN_ANGLE = -15.0; + private const double MAX_ANGLE = 15.0; + private const double INCREMENT = 0.1; + private const int MIN_SLIDER_SIZE = 250; + private const int TEMP_PIXBUF_SIZE = 768; + + private class StraightenToolWindow : EditingToolWindow { + public const int CONTROL_SPACING = 8; + + public Gtk.HScale angle_slider = new Gtk.HScale.with_range(MIN_ANGLE, MAX_ANGLE, INCREMENT); + public Gtk.Label angle_label = new Gtk.Label(""); + public Gtk.Label description_label = new Gtk.Label(_("Angle:")); + public Gtk.Button ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK); + public Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL); + public Gtk.Button reset_button = new Gtk.Button.with_mnemonic(_("_Reset")); + + /** + * Prepare straighten tool's window for use and initialize all its controls. + * + * @param container The application's main window. + */ + public StraightenToolWindow(Gtk.Window container) { + base(container); + + angle_slider.set_min_slider_size(MIN_SLIDER_SIZE); + angle_slider.set_value(0.0); + angle_slider.set_draw_value(false); + + description_label.set_padding(0,0); + angle_label.set_padding(0,0); + + Gtk.HBox slider_layout = new Gtk.HBox(false, CONTROL_SPACING); + slider_layout.add(angle_slider); + + Gtk.HBox button_layout = new Gtk.HBox(false, CONTROL_SPACING); + button_layout.add(cancel_button); + button_layout.add(reset_button); + button_layout.add(ok_button); + + Gtk.HBox main_layout = new Gtk.HBox(false, 0); + main_layout.add(description_label); + main_layout.add(slider_layout); + main_layout.add(angle_label); + main_layout.add(button_layout); + + add(main_layout); + + reset_button.clicked.connect(on_reset_clicked); + + set_position(Gtk.WindowPosition.CENTER_ON_PARENT); + } + + private void on_reset_clicked() { + angle_slider.set_value(0.0); + } + } + + private StraightenToolWindow window; + + // the incoming image itself. + private Cairo.Surface photo_surf; + Dimensions image_dims; + + // temporary surface we'll draw the rotated image into. + private Cairo.Surface rotate_surf; + private Cairo.Context rotate_ctx; + + private Dimensions last_viewport; + private int view_width; + private int view_height; + private double photo_angle = 0.0; + + // should we use a nicer-but-more-expensive filter + // when repainting the rotated image? + bool use_high_qual = false; + + private Gdk.Point crop_center; // original center in image coordinates + private int crop_width; + private int crop_height; + + // As the crop box rotates, we adjust its center and/or scale it so that it fits in the image. + private Gdk.Point rotated_center; // in image coordinates + private double rotate_scale; // always <= 1.0: rotation may shrink but not grow box + + private double preview_scale; + + private StraightenTool() { + } + + public static StraightenTool factory() { + return new StraightenTool(); + } + + /** + * @brief Signal handler for when the 'OK' button has been clicked. Computes where a previously- + * set crop region should have rotated to (to match the Photo's straightening angle). + * + * @note After this has been called against a Photo, it will always have a crop region; in the + * case of a previously-uncropped Photo, the crop region will be set to the original dimensions + * of the photo and centered at the Photo's center. + */ + private void on_ok_clicked() { + assert(canvas.get_photo() != null); + + // compute where the crop box should be now and set the image's + // current crop to it + double slider_val = window.angle_slider.get_value(); + + Gdk.Point new_crop_center = rotate_point_arb(rotated_center, + image_dims.width, image_dims.height, slider_val); + + StraightenCommand command = new StraightenCommand( + canvas.get_photo(), slider_val, + Box.from_center(new_crop_center, + (int) (rotate_scale * crop_width), (int) (rotate_scale * crop_height)), + Resources.STRAIGHTEN_LABEL, Resources.STRAIGHTEN_TOOLTIP); + AppWindow.get_command_manager().execute(command); + + canvas.repaint(); + deactivate(); + } + + private void on_cancel_clicked() { + canvas.repaint(); + deactivate(); + } + + private bool on_slider_released(Gdk.EventButton geb) { + use_high_qual = true; + this.canvas.repaint(); + return false; + } + + private void prepare_image() { + Dimensions canvas_dims = canvas.get_surface_dim(); + Dimensions viewport = canvas_dims.with_max(TEMP_PIXBUF_SIZE, TEMP_PIXBUF_SIZE); + if (viewport == last_viewport) + return; // no change + + last_viewport = viewport; + + Gdk.Pixbuf low_res_tmp = null; + try { + low_res_tmp = + canvas.get_photo().get_pixbuf_with_options(Scaling.for_viewport(viewport, false), + Photo.Exception.STRAIGHTEN | Photo.Exception.CROP); + } catch (Error e) { + warning("A pixbuf for %s couldn't be fetched.", canvas.get_photo().to_string()); + low_res_tmp = new Gdk.Pixbuf(Gdk.Colorspace.RGB, false, 8, 1, 1); + } + + preview_scale = low_res_tmp.width / (double) image_dims.width; + + // copy image data from photo into a cairo surface. + photo_surf = new Cairo.ImageSurface(Cairo.Format.ARGB32, low_res_tmp.width, low_res_tmp.height); + Cairo.Context ctx = new Cairo.Context(photo_surf); + Gdk.cairo_set_source_pixbuf(ctx, low_res_tmp, 0, 0); + ctx.rectangle(0, 0, low_res_tmp.width, low_res_tmp.height); + ctx.fill(); + ctx.paint(); + + // prepare rotation surface and context. we paint a rotated, + // low-res copy of the image into it, followed by a faint grid. + view_width = (int) (crop_width * preview_scale); + view_height = (int) (crop_height * preview_scale); + rotate_surf = new Cairo.ImageSurface(Cairo.Format.ARGB32, view_width, view_height); + rotate_ctx = new Cairo.Context(rotate_surf); + } + + // Adjust the rotated crop box so that it fits in the source image. + void adjust_for_rotation() { + double width, height; + compute_arb_rotated_size(crop_width, crop_height, photo_angle, out width, out height); + + // First compute a scaling factor that will let the rotated box fit in the image. + rotate_scale = double.min(image_dims.width / width, image_dims.height / height); + rotate_scale = double.min(rotate_scale, 1.0); + + // Now nudge the box into the image if necessary. + rotated_center = crop_center; + int radius_x = (int) (rotate_scale * width / 2); + int radius_y = (int) (rotate_scale * height / 2); + rotated_center.x = rotated_center.x.clamp(radius_x, image_dims.width - radius_x); + rotated_center.y = rotated_center.y.clamp(radius_y, image_dims.height - radius_y); + } + + /** + * @brief Spawn the tool window, set up the scratch surfaces and prepare the straightening + * tool for use. If a valid pixbuf of the incoming Photo can't be loaded for any + * reason, the tool will use a 1x1 temporary image instead to avoid crashing. + * + * @param canvas The PhotoCanvas the tool's output should be painted to. + */ + public override void activate(PhotoCanvas canvas) { + base.activate(canvas); + this.canvas = canvas; + bind_canvas_handlers(this.canvas); + + image_dims = canvas.get_photo().get_dimensions( + Photo.Exception.STRAIGHTEN | Photo.Exception.CROP); + + Box crop_region; + if (!canvas.get_photo().get_crop(out crop_region)) { + crop_region.left = 0; + crop_region.right = image_dims.width; + + crop_region.top = 0; + crop_region.bottom = image_dims.height; + } + + // read the photo's current angle and start the tool with the slider set to that value. we + // also use this to de-rotate the crop region + double incoming_angle = 0.0; + canvas.get_photo().get_straighten(out incoming_angle); + + // Translate the crop center to image coordinates. + crop_center = derotate_point_arb(crop_region.get_center(), + image_dims.width, image_dims.height, incoming_angle); + crop_width = crop_region.get_width(); + crop_height = crop_region.get_height(); + + adjust_for_rotation(); + + prepare_image(); + + window = new StraightenToolWindow(canvas.get_container()); + bind_window_handlers(); + + // prepare ths slider for display + window.angle_slider.set_value(incoming_angle); + photo_angle = incoming_angle; + + string tmp = "%2.1f°".printf(incoming_angle); + window.angle_label.set_text(tmp); + + window.show_all(); + } + + /** + * Tears down the tool window and frees resources. + */ + public override void deactivate() { + if(window != null) { + + unbind_window_handlers(); + + window.hide(); + window = null; + } + + if (canvas != null) { + unbind_canvas_handlers(canvas); + } + + base.deactivate(); + } + + private void bind_canvas_handlers(PhotoCanvas canvas) { + canvas.resized_scaled_pixbuf.connect(on_resized_pixbuf); + } + + private void unbind_canvas_handlers(PhotoCanvas canvas) { + canvas.resized_scaled_pixbuf.disconnect(on_resized_pixbuf); + } + + private void bind_window_handlers() { + window.ok_button.clicked.connect(on_ok_clicked); + window.cancel_button.clicked.connect(on_cancel_clicked); + window.angle_slider.value_changed.connect(on_angle_changed); + window.angle_slider.button_release_event.connect(on_slider_released); + } + + private void unbind_window_handlers() { + window.ok_button.clicked.disconnect(on_ok_clicked); + window.cancel_button.clicked.disconnect(on_cancel_clicked); + window.angle_slider.value_changed.disconnect(on_angle_changed); + window.angle_slider.button_release_event.disconnect(on_slider_released); + } + + private void on_angle_changed() { + photo_angle = window.angle_slider.get_value(); + string tmp = "%2.1f°".printf(window.angle_slider.get_value()); + window.angle_label.set_text(tmp); + + use_high_qual = false; + + adjust_for_rotation(); + this.canvas.repaint(); + } + + /** + * @brief Called by the EditingHostPage when a resize event occurs. + */ + private void on_resized_pixbuf(Dimensions old_dim, Gdk.Pixbuf scaled, Gdk.Rectangle scaled_position) { + prepare_image(); + } + + /** + * Returns a reference to the current StraightenTool instance's tool window; + * the PhotoPage uses this to control the tool window's positioning, etc. + */ + public override EditingToolWindow? get_tool_window() { + return window; + } + + /** + * Render a smaller, rotated version of the image, with a grid superimposed over it. + * + * @param ctx The rendering context of a 'scratch' Cairo surface. The tool makes its own + * surfaces and contexts so it can have things set up exactly like it wants them, so + * it's not used. + */ + public override void paint(Cairo.Context ctx) { + int w = canvas.get_drawing_window().get_width(); + int h = canvas.get_drawing_window().get_height(); + + // draw the rotated photo and grid. + draw_rotated_source(photo_surf, rotate_ctx, view_width, view_height, photo_angle); + draw_superimposed_grid(rotate_ctx, view_width, view_height); + + // fill region behind the rotation surface with neutral color. + canvas.get_default_ctx().identity_matrix(); + canvas.get_default_ctx().set_source_rgba(0.0, 0.0, 0.0, 1.0); + canvas.get_default_ctx().rectangle(0, 0, w, h); + canvas.get_default_ctx().fill(); + + // copy the composited result to the main window. + canvas.get_default_ctx().translate((w - view_width) / 2.0, (h - view_height) / 2.0); + canvas.get_default_ctx().set_source_surface(rotate_surf, 0, 0); + canvas.get_default_ctx().rectangle(0, 0, view_width, view_height); + canvas.get_default_ctx().fill(); + canvas.get_default_ctx().paint(); + + // reset the 'modelview' matrix, since when the canvas is not in + // 'tool' mode, it 'expects' things to be set up a certain way. + canvas.get_default_ctx().identity_matrix(); + } + + /** + * Copy a rotated version of the source image onto the destination + * context. + * + * @param src_surf A Cairo surface containing the source image. + * @param dest_ctx The rendering context of the destination image. + * @param src_width The width of the image data in src_surf in pixels. + * @param src_height The height of the image data in src_surf in pixels. + * @param angle The angle the source image should be rotated by, in degrees. + */ + private void draw_rotated_source(Cairo.Surface src_surf, Cairo.Context dest_ctx, + int src_width, int src_height, double angle) { + double angle_internal = degrees_to_radians(angle); + + // fill area behind rotated image with neutral color to avoid 'ghosting'. + // this should be removed after #4612 has been addressed. + dest_ctx.identity_matrix(); + dest_ctx.set_source_rgba(0.0, 0.0, 0.0, 1.0); + dest_ctx.rectangle(0, 0, view_width, view_height); + dest_ctx.fill(); + + // rotate the image, taking into account that the position of the + // upper left corner must change depending on rotation amount and direction + // and translate so center of preview crop region is now center of rotation + dest_ctx.identity_matrix(); + + dest_ctx.translate(view_width / 2, view_height / 2); + dest_ctx.scale(1.0 / rotate_scale, 1.0 / rotate_scale); + dest_ctx.rotate(angle_internal); + dest_ctx.translate(- rotated_center.x * preview_scale, - rotated_center.y * preview_scale); + + dest_ctx.set_source_surface(src_surf, 0, 0); + dest_ctx.get_source().set_filter(use_high_qual ? Cairo.Filter.BEST : Cairo.Filter.NEAREST); + dest_ctx.rectangle(0, 0, src_width, src_height); + dest_ctx.fill(); + dest_ctx.paint(); + } + + /** + * Superimpose a faint grid over the supplied image. + * + * @param width The total width the grid should be drawn to. + * @param height The total height the grid should be drawn to. + * @param dest_ctx The rendering context of the destination image. + */ + private void draw_superimposed_grid(Cairo.Context dest_ctx, int width, int height) { + int half_width = width / 2; + int quarter_width = width / 4; + + int half_height = height / 2; + int quarter_height = height / 4; + + dest_ctx.identity_matrix(); + dest_ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0); + + canvas.draw_horizontal_line(dest_ctx, 0, 0, width, false); + canvas.draw_horizontal_line(dest_ctx, 0, half_height, width, false); + canvas.draw_horizontal_line(dest_ctx, 0, view_height, width, false); + + canvas.draw_vertical_line(dest_ctx, 0, 0, height, false); + canvas.draw_vertical_line(dest_ctx, half_width, 0, height, false); + canvas.draw_vertical_line(dest_ctx, width, 0, height, false); + + dest_ctx.set_source_rgba(1.0, 1.0, 1.0, 0.33); + + canvas.draw_horizontal_line(dest_ctx, 0, quarter_height, width, false); + canvas.draw_horizontal_line(dest_ctx, 0, half_height + quarter_height, width, false); + canvas.draw_vertical_line(dest_ctx, quarter_width, 0, height, false); + canvas.draw_vertical_line(dest_ctx, half_width + quarter_width, 0, height, false); + } +} + +} // end namespace diff -Nru shotwell-0.11.91/src/events/Branch.vala shotwell-0.11.92/src/events/Branch.vala --- shotwell-0.11.91/src/events/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/events/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/events/EventDirectoryItem.vala shotwell-0.11.92/src/events/EventDirectoryItem.vala --- shotwell-0.11.91/src/events/EventDirectoryItem.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/events/EventDirectoryItem.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/events/EventPage.vala shotwell-0.11.92/src/events/EventPage.vala --- shotwell-0.11.91/src/events/EventPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/events/EventPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/events/EventsDirectoryPage.vala shotwell-0.11.92/src/events/EventsDirectoryPage.vala --- shotwell-0.11.91/src/events/EventsDirectoryPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/events/EventsDirectoryPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/events/Events.vala shotwell-0.11.92/src/events/Events.vala --- shotwell-0.11.91/src/events/Events.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/events/Events.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Event.vala shotwell-0.11.92/src/Event.vala --- shotwell-0.11.91/src/Event.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Event.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Exporter.vala shotwell-0.11.92/src/Exporter.vala --- shotwell-0.11.91/src/Exporter.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Exporter.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/faces/Branch.vala shotwell-0.11.92/src/faces/Branch.vala --- shotwell-0.11.91/src/faces/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/faces/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/faces/FaceLocation.vala shotwell-0.11.92/src/faces/FaceLocation.vala --- shotwell-0.11.91/src/faces/FaceLocation.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/faces/FaceLocation.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/faces/FacePage.vala shotwell-0.11.92/src/faces/FacePage.vala --- shotwell-0.11.91/src/faces/FacePage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/faces/FacePage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/faces/FaceShape.vala shotwell-0.11.92/src/faces/FaceShape.vala --- shotwell-0.11.91/src/faces/FaceShape.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/faces/FaceShape.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/faces/Faces.vala shotwell-0.11.92/src/faces/Faces.vala --- shotwell-0.11.91/src/faces/Faces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/faces/Faces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/faces/Face.vala shotwell-0.11.92/src/faces/Face.vala --- shotwell-0.11.91/src/faces/Face.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/faces/Face.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/International.vala shotwell-0.11.92/src/International.vala --- shotwell-0.11.91/src/International.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/International.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/Branch.vala shotwell-0.11.92/src/library/Branch.vala --- shotwell-0.11.91/src/library/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/FlaggedBranch.vala shotwell-0.11.92/src/library/FlaggedBranch.vala --- shotwell-0.11.91/src/library/FlaggedBranch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/FlaggedBranch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/FlaggedPage.vala shotwell-0.11.92/src/library/FlaggedPage.vala --- shotwell-0.11.91/src/library/FlaggedPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/FlaggedPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/ImportQueueBranch.vala shotwell-0.11.92/src/library/ImportQueueBranch.vala --- shotwell-0.11.91/src/library/ImportQueueBranch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/ImportQueueBranch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/ImportQueuePage.vala shotwell-0.11.92/src/library/ImportQueuePage.vala --- shotwell-0.11.91/src/library/ImportQueuePage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/ImportQueuePage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/LastImportBranch.vala shotwell-0.11.92/src/library/LastImportBranch.vala --- shotwell-0.11.91/src/library/LastImportBranch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/LastImportBranch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/LastImportPage.vala shotwell-0.11.92/src/library/LastImportPage.vala --- shotwell-0.11.91/src/library/LastImportPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/LastImportPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/Library.vala shotwell-0.11.92/src/library/Library.vala --- shotwell-0.11.91/src/library/Library.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/Library.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/LibraryWindow.vala shotwell-0.11.92/src/library/LibraryWindow.vala --- shotwell-0.11.91/src/library/LibraryWindow.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/LibraryWindow.vala 2012-02-21 00:41:45.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -69,7 +69,7 @@ // special Yorba-selected sidebar background color for standard themes (humanity, // clearlooks, etc.); dark themes use the theme's native background color - public static Gdk.Color SIDEBAR_STANDARD_BG_COLOR = parse_color("#EEE"); + public static Gdk.RGBA SIDEBAR_STANDARD_BG_COLOR = parse_color("#EEE"); // Max brightness value to trigger SIDEBAR_STANDARD_BG_COLOR public const uint16 STANDARD_COMPONENT_MINIMUM = 0xe000; @@ -388,11 +388,12 @@ import.tooltip = _("Import photos from disk to library"); actions += import; - // Add one action per alien database driver - foreach (AlienDb.AlienDatabaseDriver driver in AlienDb.AlienDatabaseHandler.get_instance().get_drivers()) { - Gtk.ActionEntry import_from_alien_db = driver.get_action_entry(); - actions += import_from_alien_db; - } + Gtk.ActionEntry import_from_external = { + "ExternalLibraryImport", Resources.IMPORT, TRANSLATABLE, + "E", TRANSLATABLE, on_external_library_import + }; + import_from_external.label = _("Import From _Application..."); + actions += import_from_external; Gtk.ActionEntry sort = { "CommonSortEvents", null, TRANSLATABLE, null, null, null }; sort.label = _("Sort _Events"); @@ -499,11 +500,6 @@ public override void replace_common_placeholders(Gtk.UIManager ui) { base.replace_common_placeholders(ui); - - // Adds one menu entry per alien database driver - AlienDb.AlienDatabaseHandler.get_instance().add_menu_entries( - ui, "/MenuBar/FileMenu/CommonImportFromAlienDbPlaceholder" - ); } protected override void switched_pages(Page? old_page, Page? new_page) { @@ -744,6 +740,12 @@ import_dialog.destroy(); } + private void on_external_library_import() { + Gtk.Dialog import_dialog = DataImportsUI.DataImportsDialog.get_or_create_instance(); + + import_dialog.run(); + } + protected override void update_common_action_availability(Page? old_page, Page? new_page) { base.update_common_action_availability(old_page, new_page); @@ -959,7 +961,8 @@ private Gdk.DragAction get_drag_action() { Gdk.ModifierType mask; - get_window().get_pointer(null, null, out mask); + get_window().get_device_position(Gdk.Display.get_default().get_device_manager() + .get_client_pointer(), null, null, out mask); bool ctrl = (mask & Gdk.ModifierType.CONTROL_MASK) != 0; bool alt = (mask & Gdk.ModifierType.MOD1_MASK) != 0; @@ -1354,7 +1357,7 @@ // if the current theme is a standard theme (as opposed to a dark theme), then // use the specially-selected Yorba muted background color for the sidebar. // otherwise, use the theme's native background color. - sidebar_tree.modify_base(Gtk.StateType.NORMAL, SIDEBAR_STANDARD_BG_COLOR); + sidebar_tree.override_color(Gtk.StateFlags.NORMAL, SIDEBAR_STANDARD_BG_COLOR); } // put the sidebar in a scrolling window diff -Nru shotwell-0.11.91/src/library/mk/library.mk shotwell-0.11.92/src/library/mk/library.mk --- shotwell-0.11.91/src/library/mk/library.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/mk/library.mk 2012-02-20 20:47:27.000000000 +0000 @@ -36,15 +36,14 @@ Slideshow \ Photos \ Publishing \ - AlienDb \ - AlienDb.FSpot \ Core \ Sidebar \ Events \ Tags \ Camera \ Searches \ - Faces + Faces \ + DataImports # List any additional files that are used in the build process as a part of this unit that should # be packaged in the tarball. File names should be relative to the unit's home directory. diff -Nru shotwell-0.11.91/src/library/OfflineBranch.vala shotwell-0.11.92/src/library/OfflineBranch.vala --- shotwell-0.11.91/src/library/OfflineBranch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/OfflineBranch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/OfflinePage.vala shotwell-0.11.92/src/library/OfflinePage.vala --- shotwell-0.11.91/src/library/OfflinePage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/OfflinePage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/TrashBranch.vala shotwell-0.11.92/src/library/TrashBranch.vala --- shotwell-0.11.91/src/library/TrashBranch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/TrashBranch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/library/TrashPage.vala shotwell-0.11.92/src/library/TrashPage.vala --- shotwell-0.11.91/src/library/TrashPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/library/TrashPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/LibraryFiles.vala shotwell-0.11.92/src/LibraryFiles.vala --- shotwell-0.11.91/src/LibraryFiles.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/LibraryFiles.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -87,9 +87,9 @@ // Make file writable by getting current Unix mode and or it with 600 (user read/write) try { - FileInfo info = dest.query_info(FILE_ATTRIBUTE_UNIX_MODE, FileQueryInfoFlags.NONE); - uint32 mode = info.get_attribute_uint32(FILE_ATTRIBUTE_UNIX_MODE) | 0600; - if (!dest.set_attribute_uint32(FILE_ATTRIBUTE_UNIX_MODE, mode, FileQueryInfoFlags.NONE)) { + FileInfo info = dest.query_info(FileAttribute.UNIX_MODE, FileQueryInfoFlags.NONE); + uint32 mode = info.get_attribute_uint32(FileAttribute.UNIX_MODE) | 0600; + if (!dest.set_attribute_uint32(FileAttribute.UNIX_MODE, mode, FileQueryInfoFlags.NONE)) { warning("Could not make file writable"); } } catch (Error err) { diff -Nru shotwell-0.11.91/src/LibraryMonitor.vala shotwell-0.11.92/src/LibraryMonitor.vala --- shotwell-0.11.91/src/LibraryMonitor.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/LibraryMonitor.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/main.vala shotwell-0.11.92/src/main.vala --- shotwell-0.11.91/src/main.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/main.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -204,20 +204,25 @@ library_window.show_all(); + WelcomeServiceEntry[] selected_import_entries = new WelcomeServiceEntry[0]; if (Config.Facade.get_instance().get_show_welcome_dialog() && LibraryPhoto.global.get_count() == 0) { WelcomeDialog welcome = new WelcomeDialog(library_window); - Config.Facade.get_instance().set_show_welcome_dialog(welcome.execute(out do_fspot_import, + Config.Facade.get_instance().set_show_welcome_dialog(welcome.execute(out selected_import_entries, out do_system_pictures_import)); } else { Config.Facade.get_instance().set_show_welcome_dialog(false); } - if (do_fspot_import) { - // TODO: remove dependency on FSpot - AlienDb.FSpot.FSpotDatabaseDriver.do_import(report_fspot_import); - } else if (do_system_pictures_import) { /* else-if because f-spot import will run the system - pictures import automatically if it's requested */ + if (selected_import_entries.length > 0) { + do_external_import = true; + foreach (WelcomeServiceEntry entry in selected_import_entries) + entry.execute(); + } + if (do_system_pictures_import) { + /* Do the system import even if other plugins have run as some plugins may not + as some plugins may not import pictures from the system folder. + */ run_system_pictures_import(); } @@ -244,9 +249,9 @@ } private bool do_system_pictures_import = false; -private bool do_fspot_import = false; +private bool do_external_import = false; -public void run_system_pictures_import(ImportManifest? fspot_exclusion_manifest = null) { +public void run_system_pictures_import(ImportManifest? external_exclusion_manifest = null) { if (!do_system_pictures_import) return; @@ -256,27 +261,20 @@ LibraryWindow library_window = (LibraryWindow) AppWindow.get_instance(); BatchImport batch_import = new BatchImport(jobs, "startup_import", - report_system_pictures_import, null, null, null, null, fspot_exclusion_manifest); + report_system_pictures_import, null, null, null, null, external_exclusion_manifest); library_window.enqueue_batch_import(batch_import, true); library_window.switch_to_import_queue_page(); } -private void report_fspot_import(ImportManifest manifest, BatchImportRoll import_roll) { - ImportUI.report_manifest(manifest, true); - - if (do_system_pictures_import) - run_system_pictures_import(manifest); -} - private void report_system_pictures_import(ImportManifest manifest, BatchImportRoll import_roll) { - /* Don't report the manifest to the user if F-Spot import was done and the entire manifest + /* Don't report the manifest to the user if exteral import was done and the entire manifest is empty. An empty manifest in this case results from files that were already imported - in the F-Spot import phase being skipped. Note that we are testing against manifest.all, + in the external import phase being skipped. Note that we are testing against manifest.all, not manifest.success; manifest.all is zero when no files were enqueued for import in the first place and the only way this happens is if all files were skipped -- even failed files are counted in manifest.all */ - if (do_fspot_import && (manifest.all.size == 0)) + if (do_external_import && (manifest.all.size == 0)) return; ImportUI.report_manifest(manifest, true); diff -Nru shotwell-0.11.91/src/MediaDataRepresentation.vala shotwell-0.11.92/src/MediaDataRepresentation.vala --- shotwell-0.11.91/src/MediaDataRepresentation.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MediaDataRepresentation.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -169,7 +169,7 @@ public abstract void increase_rating(); public abstract void decrease_rating(); - public abstract Dimensions get_dimensions(); + public abstract Dimensions get_dimensions(Photo.Exception disallowed_steps = Photo.Exception.NONE); // A preview pixbuf is one that can be quickly generated and scaled as a preview. For media // type that support transformations (i.e. photos) it is fully transformed. diff -Nru shotwell-0.11.91/src/MediaInterfaces.vala shotwell-0.11.92/src/MediaInterfaces.vala --- shotwell-0.11.91/src/MediaInterfaces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MediaInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/MediaMetadata.vala shotwell-0.11.92/src/MediaMetadata.vala --- shotwell-0.11.91/src/MediaMetadata.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MediaMetadata.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/MediaMonitor.vala shotwell-0.11.92/src/MediaMonitor.vala --- shotwell-0.11.91/src/MediaMonitor.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MediaMonitor.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/MediaPage.vala shotwell-0.11.92/src/MediaPage.vala --- shotwell-0.11.91/src/MediaPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MediaPage.vala 2012-02-21 00:34:13.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/MediaViewTracker.vala shotwell-0.11.92/src/MediaViewTracker.vala --- shotwell-0.11.91/src/MediaViewTracker.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MediaViewTracker.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/MetadataWriter.vala shotwell-0.11.92/src/MetadataWriter.vala --- shotwell-0.11.91/src/MetadataWriter.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/MetadataWriter.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Orientation.vala shotwell-0.11.92/src/Orientation.vala --- shotwell-0.11.91/src/Orientation.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Orientation.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Page.vala shotwell-0.11.92/src/Page.vala --- shotwell-0.11.91/src/Page.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Page.vala 2012-02-21 00:41:45.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -380,7 +380,8 @@ int x, y; Gdk.ModifierType mask; - AppWindow.get_instance().get_window().get_pointer(out x, out y, out mask); + AppWindow.get_instance().get_window().get_device_position(Gdk.Display.get_default(). + get_device_manager().get_client_pointer(), out x, out y, out mask); ctrl = (mask & Gdk.ModifierType.CONTROL_MASK) != 0; alt = (mask & Gdk.ModifierType.MOD1_MASK) != 0; @@ -678,7 +679,8 @@ return false; } - event_source.get_window().get_pointer(out x, out y, out mask); + event_source.get_window().get_device_position(Gdk.Display.get_default().get_device_manager() + .get_client_pointer(), out x, out y, out mask); if (last_down.x < 0 || last_down.y < 0) return true; @@ -1004,7 +1006,7 @@ private bool on_motion_internal(Gdk.EventMotion event) { int x, y; Gdk.ModifierType mask; - if (event.is_hint) { + if (event.is_hint == 1) { get_event_source_pointer(out x, out y, out mask); } else { x = (int) event.x; @@ -1908,10 +1910,16 @@ viewport.add(canvas); add(viewport); + + // Work around an Ubuntu Ambiance style change that causes GtkDrawingAreas to have + // transparent backgrounds, causing odd display quirks. The color we set here is + // arbitrary. + // See https://bugs.launchpad.net/light-themes/+bug/931630 . + canvas.override_background_color(Gtk.StateFlags.NORMAL, parse_color("#000")); - // turn off double-buffering because all painting happens in pixmap, and is sent to the window - // wholesale in on_canvas_expose + // all painting happens in pixmap, and is sent to the window wholesale in on_canvas_expose canvas.set_double_buffered(false); + canvas.add_events(Gdk.EventMask.EXPOSURE_MASK | Gdk.EventMask.STRUCTURE_MASK | Gdk.EventMask.SUBSTRUCTURE_MASK); @@ -1981,7 +1989,7 @@ assert(is_zoom_supported()); Cairo.Context canvas_ctx = Gdk.cairo_create(canvas.get_window()); - Gdk.cairo_set_source_color(pixmap_ctx, canvas.get_style().black); + set_source_color_from_string(pixmap_ctx, "#000"); pixmap_ctx.paint(); bool old_quality_setting = zoom_high_quality; @@ -1997,7 +2005,7 @@ assert(is_zoom_supported()); Cairo.Context canvas_ctx = Gdk.cairo_create(canvas.get_window()); - Gdk.cairo_set_source_color(pixmap_ctx, canvas.style.black); + set_source_color_from_string(pixmap_ctx, "#000"); pixmap_ctx.paint(); bool old_quality_setting = zoom_high_quality; @@ -2015,7 +2023,7 @@ protected virtual void cancel_zoom() { if (pixmap != null) { - Gdk.cairo_set_source_color(pixmap_ctx, canvas.style.black); + set_source_color_from_string(pixmap_ctx, "#000"); pixmap_ctx.paint(); } } @@ -2172,7 +2180,7 @@ if (pixmap != null) exposed_ctx.set_source_surface(pixmap, 0, 0); else - Gdk.cairo_set_source_color(exposed_ctx, canvas.style.black); + set_source_color_from_string(exposed_ctx, "#000"); exposed_ctx.rectangle(0, 0, get_allocated_width(), get_allocated_height()); exposed_ctx.paint(); @@ -2188,14 +2196,15 @@ protected virtual void paint(Cairo.Context ctx, Dimensions ctx_dim) { if (is_zoom_supported() && (!static_zoom_state.is_default())) { - Gdk.cairo_set_source_color(ctx, canvas.style.black); + set_source_color_from_string(ctx, "#000"); ctx.rectangle(0, 0, pixmap_dim.width, pixmap_dim.height); ctx.fill(); render_zoomed_to_pixmap(static_zoom_state); } else if (!transition_clock.paint(ctx, ctx_dim.width, ctx_dim.height)) { // transition is not running, so paint the full image on a black background - Gdk.cairo_set_source_color(ctx, canvas.style.black); + set_source_color_from_string(ctx, "#000"); + ctx.rectangle(0, 0, pixmap_dim.width, pixmap_dim.height); ctx.fill(); @@ -2299,7 +2308,7 @@ if (direction != null && !transition_clock.is_in_progress()) { Spit.Transitions.Visuals visuals = new Spit.Transitions.Visuals(old_scaled, - old_scaled_pos, scaled, scaled_pos, canvas.style.black); + old_scaled_pos, scaled, scaled_pos, parse_color("#000")); transition_clock.start(visuals, direction.to_transition_direction(), transition_duration_msec, repaint_pixmap); @@ -2325,7 +2334,8 @@ // Cairo context for drawing text on the pixmap text_ctx = new Cairo.Context(pixmap); - Gdk.cairo_set_source_color(text_ctx, canvas.style.white); + set_source_color_from_string(text_ctx, "#fff"); + // no need to resize canvas, viewport does that automatically @@ -2398,7 +2408,7 @@ private static Gdk.Atom? XDS_ATOM = null; private static Gdk.Atom? TEXT_ATOM = null; - private static uchar[]? XDS_FAKE_TARGET = null; + private static uint8[]? XDS_FAKE_TARGET = null; private weak Page page; private Gtk.Widget event_source; @@ -2466,7 +2476,7 @@ // set the XDS property to indicate an XDS save is available Gdk.property_change(context.get_source_window(), XDS_ATOM, TEXT_ATOM, 8, Gdk.PropMode.REPLACE, - XDS_FAKE_TARGET, XDS_FAKE_TARGET.length); + XDS_FAKE_TARGET); } private void on_drag_data_get(Gdk.DragContext context, Gtk.SelectionData selection_data, diff -Nru shotwell-0.11.91/src/PhotoMonitor.vala shotwell-0.11.92/src/PhotoMonitor.vala --- shotwell-0.11.91/src/PhotoMonitor.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/PhotoMonitor.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/PhotoPage.vala shotwell-0.11.92/src/PhotoPage.vala --- shotwell-0.11.91/src/PhotoPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/PhotoPage.vala 2012-02-20 22:59:53.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -202,8 +202,8 @@ Gdk.Rectangle curr_rect = zoom_state.get_viewing_rectangle_wrt_content(); Gdk.Rectangle pre_rect = demand_transform_zoom_state.get_viewing_rectangle_wrt_content(); - Gdk.Rectangle transfer_src_rect = {0}; - Gdk.Rectangle transfer_dest_rect = {0}; + Gdk.Rectangle transfer_src_rect = Gdk.Rectangle(); + Gdk.Rectangle transfer_dest_rect = Gdk.Rectangle(); transfer_src_rect.x = (curr_rect.x - pre_rect.x).clamp(0, pre_rect.width); transfer_src_rect.y = (curr_rect.y - pre_rect.y).clamp(0, pre_rect.height); @@ -395,6 +395,7 @@ private Gtk.ToggleToolButton crop_button = null; private Gtk.ToggleToolButton redeye_button = null; private Gtk.ToggleToolButton adjust_button = null; + private Gtk.ToggleToolButton straighten_button = null; private Gtk.ToolButton enhance_button = null; private Gtk.HScale zoom_slider = null; private Gtk.ToolButton prev_button = new Gtk.ToolButton.from_stock(Gtk.Stock.GO_BACK); @@ -448,6 +449,14 @@ crop_button.is_important = true; toolbar.insert(crop_button, -1); + // straightening tool + straighten_button = new Gtk.ToggleToolButton.from_stock(Resources.STRAIGHTEN); + straighten_button.set_label(Resources.STRAIGHTEN_LABEL); + straighten_button.set_tooltip_text(Resources.STRAIGHTEN_TOOLTIP); + straighten_button.toggled.connect(on_straighten_toggled); + straighten_button.is_important = true; + toolbar.insert(straighten_button, -1); + // redeye reduction tool redeye_button = new Gtk.ToggleToolButton.from_stock(Resources.REDEYE); redeye_button.set_label(Resources.RED_EYE_LABEL); @@ -1455,8 +1464,16 @@ EditingTools.EditingTool tool = current_tool; current_tool = null; - // deactivate with the tool taken out of the hooks + // deactivate with the tool taken out of the hooks and + // disconnect any signals we may have connected on activating tool.deactivate(); + + tool.activated.disconnect(on_tool_activated); + tool.deactivated.disconnect(on_tool_deactivated); + tool.applied.disconnect(on_tool_applied); + tool.cancelled.disconnect(on_tool_cancelled); + tool.aborted.disconnect(on_tool_aborted); + tool = null; // only null the toggle when the tool is completely deactivated; that is, deactive the tool @@ -1783,7 +1800,7 @@ } if (photo_missing && has_photo()) { - Gdk.cairo_set_source_color(ctx, canvas.style.black); + set_source_color_from_string(ctx, "#000"); ctx.rectangle(0, 0, get_surface_dim().width, get_surface_dim().height); ctx.fill(); ctx.paint(); @@ -2018,6 +2035,10 @@ crop_button.set_active(!crop_button.get_active()); } + protected void toggle_straighten() { + straighten_button.set_active(!straighten_button.get_active()); + } + protected void toggle_redeye() { redeye_button.set_active(!redeye_button.get_active()); } @@ -2025,6 +2046,10 @@ protected void toggle_adjust() { adjust_button.set_active(!adjust_button.get_active()); } + + private void on_straighten_toggled() { + on_tool_button_toggled(straighten_button, EditingTools.StraightenTool.factory); + } private void on_crop_toggled() { on_tool_button_toggled(crop_button, EditingTools.CropTool.factory); @@ -2379,6 +2404,12 @@ crop.tooltip = Resources.CROP_TOOLTIP; actions += crop; + Gtk.ActionEntry straighten = { "Straighten", Gtk.Stock.REFRESH, TRANSLATABLE, "A", + TRANSLATABLE, toggle_straighten }; + straighten.label = Resources.STRAIGHTEN_MENU; + straighten.tooltip = Resources.STRAIGHTEN_TOOLTIP; + actions += straighten; + Gtk.ActionEntry red_eye = { "RedEye", Resources.REDEYE, TRANSLATABLE, "Y", TRANSLATABLE, toggle_redeye }; red_eye.label = Resources.RED_EYE_MENU; diff -Nru shotwell-0.11.91/src/photos/BmpSupport.vala shotwell-0.11.92/src/photos/BmpSupport.vala --- shotwell-0.11.91/src/photos/BmpSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/BmpSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/GdkSupport.vala shotwell-0.11.92/src/photos/GdkSupport.vala --- shotwell-0.11.91/src/photos/GdkSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/GdkSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/GRaw.vala shotwell-0.11.92/src/photos/GRaw.vala --- shotwell-0.11.91/src/photos/GRaw.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/GRaw.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/JfifSupport.vala shotwell-0.11.92/src/photos/JfifSupport.vala --- shotwell-0.11.91/src/photos/JfifSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/JfifSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/PhotoFileAdapter.vala shotwell-0.11.92/src/photos/PhotoFileAdapter.vala --- shotwell-0.11.91/src/photos/PhotoFileAdapter.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/PhotoFileAdapter.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/PhotoFileFormat.vala shotwell-0.11.92/src/photos/PhotoFileFormat.vala --- shotwell-0.11.91/src/photos/PhotoFileFormat.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/PhotoFileFormat.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/PhotoFileSniffer.vala shotwell-0.11.92/src/photos/PhotoFileSniffer.vala --- shotwell-0.11.91/src/photos/PhotoFileSniffer.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/PhotoFileSniffer.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/PhotoMetadata.vala shotwell-0.11.92/src/photos/PhotoMetadata.vala --- shotwell-0.11.91/src/photos/PhotoMetadata.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/PhotoMetadata.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/Photos.vala shotwell-0.11.92/src/photos/Photos.vala --- shotwell-0.11.91/src/photos/Photos.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/Photos.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/PngSupport.vala shotwell-0.11.92/src/photos/PngSupport.vala --- shotwell-0.11.91/src/photos/PngSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/PngSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/RawSupport.vala shotwell-0.11.92/src/photos/RawSupport.vala --- shotwell-0.11.91/src/photos/RawSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/RawSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/photos/TiffSupport.vala shotwell-0.11.92/src/photos/TiffSupport.vala --- shotwell-0.11.91/src/photos/TiffSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/photos/TiffSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Photo.vala shotwell-0.11.92/src/Photo.vala --- shotwell-0.11.91/src/Photo.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Photo.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -196,6 +196,10 @@ // precision limitations of various subsystems. Pixel-accuracy would be best, but barring that, // need to just make sure the pixbuf is in the ballpark. private const int SCALING_FUDGE = 64; + + // The number of seconds we should hold onto a precached copy of the original image; if + // it hasn't been accessed in this many seconds, discard it to conserve memory. + private const int PRECACHE_TIME_TO_LIVE = 180; public enum Exception { NONE = 0, @@ -292,6 +296,23 @@ private OneShotScheduler reimport_editable_scheduler = null; private OneShotScheduler update_editable_attributes_scheduler = null; private OneShotScheduler remove_editable_scheduler = null; + + // The first time we have to run the pipeline on an image, we'll precache + // a copy of the unscaled, unmodified version; this allows us to operate + // directly on the image data quickly without re-fetching it at the top + // of the pipeline, which can cause significant lag with larger images. + // + // This adds a small amount of (automatically garbage-collected) memory + // overhead, but greatly simplifies the pipeline, since scaling can now + // be blithely ignored, and most of the pixel operations are fast enough + // that the app remains responsive, even with 10MP images. + // + // In order to make sure we discard unneeded precaches in a timely fashion, + // we spawn a timer when the unmodified pixbuf is first precached; if the + // timer elapses and the pixbuf hasn't been needed again since then, we'll + // discard it and free up the memory. + private Gdk.Pixbuf unmodified_precached = null; + private GLib.Timer secs_since_access = null; // RAW only: developed backing photos. private Gee.HashMap? developments = null; @@ -553,8 +574,7 @@ File file = File.new_for_path(bpr.filepath); FileInfo info = file.query_info(DirectoryMonitor.SUPPLIED_ATTRIBUTES, FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null); - TimeVal timestamp; - info.get_modification_time(out timestamp); + TimeVal timestamp = info.get_modification_time(); PhotoFileInterrogator interrogator = new PhotoFileInterrogator( file, PhotoFileSniffer.Options.GET_ALL); @@ -684,6 +704,7 @@ } notify_altered(new Alteration("image", "developer")); + discard_prefetched(true); } public RawDeveloper get_raw_developer() { @@ -992,8 +1013,7 @@ return ImportResult.UNSUPPORTED_FORMAT; } - TimeVal timestamp; - info.get_modification_time(out timestamp); + TimeVal timestamp = info.get_modification_time(); // if all MD5s supplied, don't sniff for them if (params.exif_md5 != null && params.thumbnail_md5 != null && params.full_md5 != null) @@ -1150,8 +1170,7 @@ return null; } - TimeVal modification_time = TimeVal(); - info.get_modification_time(out modification_time); + TimeVal modification_time = info.get_modification_time(); backing.filepath = file.get_path(); backing.timestamp = modification_time.tv_sec; @@ -1198,7 +1217,7 @@ } private class ReimportRawDevelopmentStateImpl : ReimportRawDevelopmentState { - class DevToReimport { + public class DevToReimport { public BackingPhotoRow backing = new BackingPhotoRow(); public PhotoMetadata? metadata; @@ -1491,8 +1510,7 @@ // Use this only if the master file's modification time has been changed (i.e. touched) public void set_master_timestamp(FileInfo info) { - TimeVal modification; - info.get_modification_time(out modification); + TimeVal modification = info.get_modification_time(); try { lock (row) { @@ -1516,8 +1534,7 @@ // Use this only if the editable file's modification time has been changed (i.e. touched) public void update_editable_modification_time(FileInfo info) throws DatabaseError { - TimeVal modification; - info.get_modification_time(out modification); + TimeVal modification = info.get_modification_time(); bool altered = false; lock (row) { @@ -2075,8 +2092,7 @@ error("Unable to read file information for %s: %s", to_string(), err.message); } - TimeVal timestamp = TimeVal(); - info.get_modification_time(out timestamp); + TimeVal timestamp = info.get_modification_time(); // interrogate file for photo information PhotoFileInterrogator interrogator = new PhotoFileInterrogator(file); @@ -2243,13 +2259,67 @@ file_exif_updated(); } - // Returns cropped and rotated dimensions - public override Dimensions get_dimensions() { - Box crop; - if (get_crop(out crop)) - return crop.get_dimensions(); - - return get_original_dimensions(); + /** + * @brief Returns the width and height of the Photo after various + * arbitrary stages of the pipeline have been applied in + * the same order they're applied in get_pixbuf_with_options. + * With no argument passed, it works exactly like the + * previous incarnation did. + * + * @param disallowed_steps Which pipeline steps should NOT + * be taken into account when computing image dimensions + * (matching the convention set by get_pixbuf_with_options()). + * Pipeline steps that do not affect the image geometry are + * ignored. + */ + public override Dimensions get_dimensions(Exception disallowed_steps = Exception.NONE) { + // The raw dimensions of the incoming image prior to the pipeline. + Dimensions returned_dims = get_raw_dimensions(); + + // Compute how much the image would be resized by after rotating and/or mirroring. + if (disallowed_steps.allows(Exception.ORIENTATION)) { + Orientation ori_tmp = get_orientation(); + + // Is this image rotated 90 or 270 degrees? + switch (ori_tmp) { + case Orientation.LEFT_TOP: + case Orientation.RIGHT_TOP: + case Orientation.LEFT_BOTTOM: + case Orientation.RIGHT_BOTTOM: + // Yes, swap width and height of raw dimensions. + int width_tmp = returned_dims.width; + + returned_dims.width = returned_dims.height; + returned_dims.height = width_tmp; + break; + + default: + // No, only mirrored or rotated 180; do nothing. + break; + } + } + + // Compute how much the image would be resized by after straightening. + if (disallowed_steps.allows(Exception.STRAIGHTEN)) { + double x_size, y_size; + double angle = 0.0; + + get_straighten(out angle); + + compute_arb_rotated_size(returned_dims.width, returned_dims.height, angle, out x_size, out y_size); + + returned_dims.width = (int) (x_size); + returned_dims.height = (int) (y_size); + } + + // Compute how much the image would be resized by after cropping. + if (disallowed_steps.allows(Exception.CROP)) { + Box crop; + if (get_crop(out crop)) { + returned_dims = crop.get_dimensions(); + } + } + return returned_dims; } // This method *must* be called with row locked. @@ -2709,7 +2779,7 @@ } // All instances are against the coordinate system of the unrotated photo. - private void add_raw_redeye_instance(EditingTools.RedeyeInstance redeye) { + public void add_redeye_instance(EditingTools.RedeyeInstance redeye) { KeyValueMap map = get_transformation("redeye"); if (map == null) { map = new KeyValueMap("redeye"); @@ -2911,7 +2981,7 @@ out scaled_to_viewport); original_orientation = get_original_orientation(); } - + // load-and-decode and scale Gdk.Pixbuf pixbuf = load_raw_pixbuf(scaling, Exception.NONE, fetch_mode); @@ -2921,28 +2991,94 @@ #endif if (rotate) pixbuf = original_orientation.rotate_pixbuf(pixbuf); + #if MEASURE_PIPELINE orientation_time = timer.elapsed(); - + debug("MASTER PIPELINE %s (%s): orientation=%lf total=%lf", to_string(), scaling.to_string(), orientation_time, total_timer.elapsed()); #endif - + return pixbuf; } - + public override Gdk.Pixbuf get_pixbuf(Scaling scaling) throws Error { return get_pixbuf_with_options(scaling); } + + /** + * @brief Populates the cached version of the unmodified image. + */ + public void populate_prefetched() throws Error { + lock (unmodified_precached) { + // If we don't have it already, precache the original... + if (unmodified_precached == null) { + unmodified_precached = load_raw_pixbuf(Scaling.for_original(), Exception.ALL, BackingFetchMode.SOURCE); + secs_since_access = new GLib.Timer(); + GLib.Timeout.add_seconds(5, (GLib.SourceFunc)discard_prefetched); + debug("spawning new precache timeout for %s", this.to_string()); + } + } + } + + /** + * @brief Get a copy of what's in the cache. + * + * @return A Pixbuf with the image data from unmodified_precached. + */ + public Gdk.Pixbuf? get_prefetched_copy() { + lock (unmodified_precached) { + if (unmodified_precached == null) { + try { + populate_prefetched(); + } catch (Error e) { + warning("raw pixbuf for %s could not be loaded", this.to_string()); + return null; + } + } + + return unmodified_precached.copy(); + } + } + + /** + * @brief Discards the cached version of the unmodified image. + * + * @param immed Whether the cached version should be discarded now, or not. + */ + public bool discard_prefetched(bool immed = false) { + lock (unmodified_precached) { + if (secs_since_access == null) + return false; + + double tmp; + if ((secs_since_access.elapsed(out tmp) > PRECACHE_TIME_TO_LIVE) || (immed)) { + debug("pipeline not run in over %d seconds or got immediate command, discarding" + + "cached original for %s", + PRECACHE_TIME_TO_LIVE, to_string()); + unmodified_precached = null; + secs_since_access = null; + return false; + } + + return true; + } + } - // Returns a fully transformed and scaled pixbuf. Transformations may be excluded via the mask. - // If the image is smaller than the scaling, it will be returned in its actual size. The - // caller is responsible for scaling thereafter. - // - // Note that an unscaled fetch can be extremely expensive, and it's far better to specify an - // appropriate scale. + /** + * @brief Returns a fully transformed and scaled pixbuf. Transformations may be excluded via + * the mask. If the image is smaller than the scaling, it will be returned in its actual size. + * The caller is responsible for scaling thereafter. + * + * @param scaling A scaling object that describes the size the output pixbuf should be. + * @param exceptions The parts of the pipeline that should be skipped; defaults to NONE if + * left unset. + * @param fetch_mode The fetch mode; if left unset, defaults to BASELINE so that + * we get the image exactly as it is in the file. + */ public Gdk.Pixbuf get_pixbuf_with_options(Scaling scaling, Exception exceptions = Exception.NONE, BackingFetchMode fetch_mode = BackingFetchMode.BASELINE) throws Error { + #if MEASURE_PIPELINE Timer timer = new Timer(); Timer total_timer = new Timer(); @@ -2951,7 +3087,7 @@ total_timer.start(); #endif - + // If this is a RAW photo, ensure the development is ready. if (Photo.develop_raw_photos_to_files && get_master_file_format() == PhotoFileFormat.RAW && @@ -2959,10 +3095,10 @@ || fetch_mode == BackingFetchMode.SOURCE) && !is_raw_developer_complete(get_raw_developer())) set_raw_developer(get_raw_developer()); - + // to minimize holding the row lock, fetch everything needed for the pipeline up-front bool is_scaled, is_cropped, is_straightened; - Dimensions scaled_image, scaled_to_viewport; + Dimensions scaled_to_viewport; Dimensions original = Dimensions(); Dimensions scaled = Dimensions(); EditingTools.RedeyeInstance[] redeye_instances = null; @@ -2970,36 +3106,38 @@ double straightening_angle; PixelTransformer transformer = null; Orientation orientation; - + lock (row) { - // it's possible for get_raw_pixbuf to not return an image scaled to the spec'd scaling, - // particularly when the raw crop is smaller than the viewport - is_scaled = calculate_pixbuf_dimensions(scaling, exceptions, out scaled_image, - out scaled_to_viewport); - - if (is_scaled) - original = get_raw_dimensions(); + original = get_dimensions(Exception.ALL); + scaled = scaling.get_scaled_dimensions(get_dimensions(exceptions)); + scaled_to_viewport = scaled; + is_scaled = !(get_dimensions().equals(scaled)); + redeye_instances = get_raw_redeye_instances(); is_cropped = get_raw_crop(out crop); - + is_straightened = get_raw_straighten(out straightening_angle); if (has_color_adjustments()) transformer = get_pixel_transformer(); - + orientation = get_orientation(); } // // Image load-and-decode // - - Gdk.Pixbuf pixbuf = load_raw_pixbuf(scaling, exceptions, fetch_mode); - - if (is_scaled) - scaled = Dimensions.for_pixbuf(pixbuf); + populate_prefetched(); + + Gdk.Pixbuf pixbuf = get_prefetched_copy(); + + // remember to delete the cached copy if it isn't being used. + secs_since_access.start(); + debug("pipeline being run against %s, timer restarted.", this.to_string()); + + assert(pixbuf != null); // // Image transformation pipeline @@ -3007,18 +3145,11 @@ // redeye reduction if (exceptions.allows(Exception.REDEYE)) { + #if MEASURE_PIPELINE timer.start(); #endif foreach (EditingTools.RedeyeInstance instance in redeye_instances) { - // redeye is stored in raw coordinates; need to scale to scaled image coordinates - if (is_scaled) { - instance.center = coord_scaled_in_space(instance.center.x, instance.center.y, - original, scaled); - instance.radius = radius_scaled_in_space(instance.radius, original, scaled); - assert(instance.radius != -1); - } - pixbuf = do_redeye(pixbuf, instance); } #if MEASURE_PIPELINE @@ -3031,13 +3162,14 @@ #if MEASURE_PIPELINE timer.start(); #endif - if(is_straightened) { + if (is_straightened) { pixbuf = rotate_arb(pixbuf, straightening_angle); } + #if MEASURE_PIPELINE straighten_time = timer.elapsed(); #endif - } + } // crop if (exceptions.allows(Exception.CROP)) { @@ -3045,58 +3177,69 @@ timer.start(); #endif if (is_cropped) { - // crop is stored in raw coordinates; need to scale to scaled image coordinates; - // also, no need to do this if the image itself was unscaled (which can happen - // if the crop is smaller than the viewport) - if (is_scaled) - crop = crop.get_scaled_similar(original, scaled); - + + // ensure the crop region stays inside the scaled image boundaries and is + // at least 1 px by 1 px; this is needed as a work-around for inaccuracies + // which can occur when zooming. + crop.left = crop.left.clamp(0, pixbuf.width - 2); + crop.top = crop.top.clamp(0, pixbuf.height - 2); + + crop.right = crop.right.clamp(crop.left + 1, pixbuf.width - 1); + crop.bottom = crop.bottom.clamp(crop.top + 1, pixbuf.height - 1); + pixbuf = new Gdk.Pixbuf.subpixbuf(pixbuf, crop.left, crop.top, crop.get_width(), - crop.get_height()); + crop.get_height()); } #if MEASURE_PIPELINE crop_time = timer.elapsed(); #endif } - - // color adjustment - if (exceptions.allows(Exception.ADJUST)) { + + // orientation (all modifications are stored in unrotated coordinate system) + if (exceptions.allows(Exception.ORIENTATION)) { #if MEASURE_PIPELINE timer.start(); #endif - if (transformer != null) - transformer.transform_pixbuf(pixbuf); + pixbuf = orientation.rotate_pixbuf(pixbuf); #if MEASURE_PIPELINE - adjustment_time = timer.elapsed(); + orientation_time = timer.elapsed(); #endif } + +#if MEASURE_PIPELINE + debug("PIPELINE %s (%s): redeye=%lf crop=%lf adjustment=%lf orientation=%lf total=%lf", + to_string(), scaling.to_string(), redeye_time, crop_time, adjustment_time, + orientation_time, total_timer.elapsed()); +#endif - // orientation (all modifications are stored in unrotated coordinate system) - if (exceptions.allows(Exception.ORIENTATION)) { + // scale the scratch image, as needed. + if (is_scaled) { + pixbuf = pixbuf.scale_simple(scaled_to_viewport.width, scaled_to_viewport.height, Gdk.InterpType.BILINEAR); + } + + // color adjustment; we do this dead last, since, if an image has been scaled down, + // it may allow us to reduce the amount of pixel arithmetic, increasing responsiveness. + if (exceptions.allows(Exception.ADJUST)) { #if MEASURE_PIPELINE timer.start(); #endif - pixbuf = orientation.rotate_pixbuf(pixbuf); + if (transformer != null) + transformer.transform_pixbuf(pixbuf); #if MEASURE_PIPELINE - orientation_time = timer.elapsed(); + adjustment_time = timer.elapsed(); #endif - } - + } + // This is to verify the generated pixbuf matches the scale requirements; crop, straighten // and orientation are all transformations that change the dimensions or aspect ratio of // the pixbuf, and must be accounted for the test to be valid. if ((is_scaled) && (!is_straightened)) assert(scaled_to_viewport.approx_equals(Dimensions.for_pixbuf(pixbuf), SCALING_FUDGE)); - -#if MEASURE_PIPELINE - debug("PIPELINE %s (%s): redeye=%lf crop=%lf adjustment=%lf orientation=%lf total=%lf", - to_string(), scaling.to_string(), redeye_time, crop_time, adjustment_time, - orientation_time, total_timer.elapsed()); -#endif - + return pixbuf; } + // // File export @@ -3425,7 +3568,7 @@ editable_monitor = null; } - private void attach_editable(PhotoFileFormat file_format, File file) throws Error { + private void attach_editable(PhotoFileFormat file_format, File file) throws Error { // remove the transformations ... this must be done before attaching the editable, as these // transformations are in the master's coordinate system, not the editable's ... don't // notify photo is altered *yet* because update_editable will notify, and want to avoid @@ -3439,8 +3582,6 @@ } public void reimport_editable() throws Error { - // remove transformations, for much the same reasons as attach_editable(). - internal_remove_all_transformations(false); update_editable(false, null); } @@ -3502,8 +3643,7 @@ return; } - TimeVal timestamp; - info.get_modification_time(out timestamp); + TimeVal timestamp = info.get_modification_time(); BackingPhotoTable.get_instance().update_attributes(editable_id, timestamp.tv_sec, info.get_size()); @@ -3665,9 +3805,16 @@ // ignored break; } + + // at this point, any image date we have cached is stale, + // so delete it and force the pipeline to re-fetch it + discard_prefetched(true); } private void on_reimport_editable() { + // delete old image data and force the pipeline to load new from file. + discard_prefetched(true); + debug("Reimporting editable for %s", to_string()); try { reimport_editable(); @@ -3728,7 +3875,7 @@ return false; } - Dimensions dim = get_raw_dimensions(); + Dimensions dim = get_dimensions(Exception.CROP | Exception.ORIENTATION); Orientation orientation = get_orientation(); crop = orientation.rotate_box(dim, raw); @@ -3737,14 +3884,17 @@ } // Sets the crop against the coordinate system of the rotated photo - public void set_crop(Box crop) { - Dimensions dim = get_raw_dimensions(); + public void set_crop(Box crop) { + Dimensions dim = get_dimensions(Exception.CROP | Exception.ORIENTATION); Orientation orientation = get_orientation(); Box derotated = orientation.derotate_box(dim, crop); - - assert(derotated.get_width() <= dim.width); - assert(derotated.get_height() <= dim.height); + + derotated.left = derotated.left.clamp(0, dim.width - 2); + derotated.right = derotated.right.clamp(derotated.left, dim.width - 1); + + derotated.top = derotated.top.clamp(0, dim.height - 2); + derotated.bottom = derotated.bottom.clamp(derotated.top, dim.height - 1); set_raw_crop(derotated); } @@ -3760,14 +3910,6 @@ set_raw_straighten(theta); } - public void add_redeye_instance(EditingTools.RedeyeInstance inst_unscaled) { - Gdk.Rectangle bounds_rect_unscaled = EditingTools.RedeyeInstance.to_bounds_rect(inst_unscaled); - Gdk.Rectangle bounds_rect_raw = unscaled_to_raw_rect(bounds_rect_unscaled); - EditingTools.RedeyeInstance inst = EditingTools.RedeyeInstance.from_bounds_rect(bounds_rect_raw); - - add_raw_redeye_instance(inst); - } - private Gdk.Pixbuf do_redeye(Gdk.Pixbuf pixbuf, EditingTools.RedeyeInstance inst) { /* we remove redeye within a circular region called the "effect extent." the effect extent is inscribed within its "bounding @@ -3909,7 +4051,7 @@ lower_right.y = temp; } - Gdk.Rectangle raw_rect = {0}; + Gdk.Rectangle raw_rect = Gdk.Rectangle(); raw_rect.x = upper_left.x; raw_rect.y = upper_left.y; raw_rect.width = lower_right.x - upper_left.x; diff -Nru shotwell-0.11.91/src/PixbufCache.vala shotwell-0.11.92/src/PixbufCache.vala --- shotwell-0.11.91/src/PixbufCache.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/PixbufCache.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/plugins/DataImportsInterfaces.vala shotwell-0.11.92/src/plugins/DataImportsInterfaces.vala --- shotwell-0.11.91/src/plugins/DataImportsInterfaces.vala 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/src/plugins/DataImportsInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,489 @@ +/* Copyright 2011 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +/** + * Shotwell Pluggable Data Imports API + * + * The Shotwell Pluggable Data Imports API allows you to write plugins that import + * information from other media library databases to help migration to Shotwell. + * The Shotwell distribution includes import support for F-Spot. + * To enable Shotwell to import from additional libaries, developers like you write + * data import plugins, dynamically-loadable shared objects that are linked into the + * Shotwell process at runtime. Data import plugins are just one of several kinds of + * plugins supported by {@link Spit}, the Shotwell Pluggable Interfaces Technology. + */ +namespace Spit.DataImports { + +/** + * The current version of the Pluggable Data Import API + */ +public const int CURRENT_INTERFACE = 0; + +/** + * The error domain for alien databases + */ +public errordomain DataImportError { + /** + * Indicates that the version of the external database being imported is + * not supported by this version of the plugin. + * + * This occurs for example when trying to import an F-Spot database that + * has a version that is more recent than what the current plugin supports. + */ + UNSUPPORTED_VERSION +} + +/** + * Represents a module that is able to import data from a specific database format. + * + * Developers of data import plugins provide a class that implements this interface. At + * any given time, only one DataImporter can be running. When a data importer is running, it + * has exclusive use of the shared user-interface and + * configuration services provided by the {@link PluginHost}. Data importers are created in + * a non-running state and do not begin running until start( ) is invoked. Data importers + * run until stop( ) is invoked. + */ +public interface DataImporter : GLib.Object { + /** + * Returns a {@link Service} object describing the service to which this connects. + */ + public abstract Service get_service(); + + /** + * Makes this data importer enter the running state and endows it with exclusive access + * to the shared services provided by the {@link PluginHost}. Through the host’s interface, + * this data importer can install user interface panes and query configuration information. + */ + public abstract void start(); + + /** + * Returns true if this data importer is in the running state; false otherwise. + */ + public abstract bool is_running(); + + /** + * Causes this data importer to enter a non-running state. This data importer should stop all + * data access operations and cease use of the shared services provided by the {@link PluginHost}. + */ + public abstract void stop(); + + /** + * Causes this data importer to enter start the import of a library. + */ + public abstract void on_library_selected(ImportableLibrary library); + + /** + * Causes this data importer to enter start the import of a library file. + */ + public abstract void on_file_selected(File file); + + // + // For future expansion. + // + protected virtual void reserved0() {} + protected virtual void reserved1() {} + protected virtual void reserved2() {} + protected virtual void reserved3() {} + protected virtual void reserved4() {} + protected virtual void reserved5() {} + protected virtual void reserved6() {} + protected virtual void reserved7() {} +} + +/** + * Represents a libary of importable media items. + * + * Developers of data import plugins provide a class that implements this interface. + */ +public interface ImportableLibrary : GLib.Object { + public abstract string get_display_name(); +} + +/** + * Represents an importable media item such as a photo or a video file. + * + * Developers of data import plugins provide a class that implements this interface. + */ +public interface ImportableMediaItem : GLib.Object { + public abstract ImportableTag[] get_tags(); + + public abstract ImportableEvent? get_event(); + + public abstract ImportableRating get_rating(); + + public abstract string? get_title(); + + public abstract string get_folder_path(); + + public abstract string get_filename(); +} + +/** + * Represents an importable tag. + * + * Developers of data import plugins provide a class that implements this interface. + */ +public interface ImportableTag : GLib.Object { + public abstract string get_name(); + + public abstract ImportableTag? get_parent(); +} + +/** + * Represents an importable event. + * + * Developers of data import plugins provide a class that implements this interface. + */ +public interface ImportableEvent : GLib.Object { + public abstract string get_name(); +} + +/** + * Represents an importable rating value. + * + * Developers of data import plugins provide a class that implements this interface. + * Note that the value returned by the get_value method should be a value between + * 1 and 5, unless the rating object is unrated or rejected, in which case the + * value is unspecified. + */ +public interface ImportableRating : GLib.Object { + public abstract bool is_unrated(); + + public abstract bool is_rejected(); + + public abstract int get_value(); +} + +/** + * Encapsulates a pane that can be installed in the on-screen import dialog box to + * communicate status to and to get information from the user. + * + */ +public interface DialogPane : GLib.Object { + + /** + * Describes how the on-screen publishing dialog box should look and behave when an associated + * pane is installed in the on-screen publishing dialog box. + */ + public enum GeometryOptions { + + /** + * When the associated pane is installed, the on-screen publishing dialog box will be + * sized normally and will not allow the user to change its size. + */ + NONE = 0, + + /** + * If this bit is set, when the associated pane is installed, the on-screen publishing + * dialog box will grow to a larger size. + */ + EXTENDED_SIZE = 1 << 0, + + /** + * If this bit is set, when the associated pane is installed, the on-screen publishing + * dialog box will allow the user to change its size. + */ + RESIZABLE = 1 << 1, + + /** + * If this bit is set, when the associated pane is installed, the on-screen publishing + * dialog box will grow to accomodate a full-width 1024 pixel web page. If both + * EXTENDED_SIZE and COLOSSAL_SIZE are set, EXTENDED_SIZE takes precedence. + */ + COLOSSAL_SIZE = 1 << 2; + } + + /** + * Returns the Gtk.Widget that is this pane's on-screen representation. + */ + public abstract Gtk.Widget get_widget(); + + /** + * Returns a {@link GeometryOptions} bitfield describing how the on-screen publishing dialog + * box should look and behave when this pane is installed. + */ + public abstract GeometryOptions get_preferred_geometry(); + + /** + * Invoked automatically by Shotwell when this pane has been installed into the on-screen + * publishing dialog box and become visible to the user. + */ + public abstract void on_pane_installed(); + + /** + * Invoked automatically by Shotwell when this pane has been removed from the on-screen + * publishing dialog box and is no longer visible to the user. + */ + public abstract void on_pane_uninstalled(); + + // + // For future expansion. + // + protected virtual void reserved0() {} + protected virtual void reserved1() {} + protected virtual void reserved2() {} + protected virtual void reserved3() {} + protected virtual void reserved4() {} + protected virtual void reserved5() {} + protected virtual void reserved6() {} + protected virtual void reserved7() {} +} + +/** + * Called by the data imports system at the end of an import batch to report + * to the plugin the number of items that were really imported. This enables + * the plugin to display a final message to the user. However, the plugin + * should not rely on this callback being called in order to clean up. + */ +public delegate void ImportedItemsCountCallback(int imported_items_count); + +/** + * Manages and provides services for data import plugins. + * + * Implemented inside Shotwell, the PluginHost provides an interface through which the + * developers of data import plugins can query and make changes to the import + * environment. Plugins can use the services of the PluginHost only when their + * {@link DataImporter} is in the running state. This ensures that non-running data importers + * don’t destructively interfere with the actively running importer. + */ +public interface PluginHost : GLib.Object, Spit.HostInterface { + + /** + * Specifies the label text on the push button control that appears in the + * lower-right-hand corner of the on-screen publishing dialog box. + */ + public enum ButtonMode { + CLOSE = 0, + CANCEL = 1 + } + + /** + * Notifies the user that an unrecoverable import error has occurred and halts + * the import process. + * + * @param err An error object that describes the kind of error that occurred. + */ + public abstract void post_error(Error err); + + /** + * Notifies the user that an unrecoverable import error has occurred and halts + * the import process. + * + * @param msg A message that describes the kind of error that occurred. + */ + public abstract void post_error_message(string msg); + + /** + * Starts the import process. + * + * Calling this method starts the import activity for this host. + */ + public abstract void start_importing(); + + /** + * Halts the import process. + * + * Calling this method stops all import activity and hides the on-screen import + * dialog box. + */ + public abstract void stop_importing(); + + /** + * Returns a reference to the {@link DataImporter} object that this is currently hosting. + */ + public abstract DataImporter get_data_importer(); + + /** + * Attempts to install a pane in the on-screen data import dialog box, making the pane visible + * and allowing it to interact with the user. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param pane the pane to install + * + * @param mode allows you to set the text displayed on the close/cancel button in the + * lower-right-hand corner of the on-screen data import dialog box when pane is installed. + * If mode is ButtonMode.CLOSE, the button will have the title "Close." If mode is + * ButtonMode.CANCEL, the button will be titled "Cancel." You should set mode depending on + * whether a cancellable action is in progress. For example, if your importer is in the + * middle of processing 3 of 8 videos, then mode should be ButtonMode.CANCEL. However, if + * the processing operation has completed and the success pane is displayed, then mode + * should be ButtonMode.CLOSE, because all cancellable actions have already + * occurred. + */ + public abstract void install_dialog_pane(Spit.DataImports.DialogPane pane, + ButtonMode mode = ButtonMode.CANCEL); + + /** + * Attempts to install a pane in the on-screen data import dialog box that contains + * static text. + * + * The text appears centered in the data import dialog box and is drawn in + * the system font. This is a convenience method only; similar results could be + * achieved by manually constructing a Gtk.Label widget, wrapping it inside a + * {@link DialogPane}, and installing it manually with a call to + * install_dialog_pane( ). To provide visual consistency across data import services, + * however, always use this convenience method instead of constructing label panes when + * you need to display static text to the user. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param message the text to show in the pane + * + * @param mode allows you to set the text displayed on the close/cancel button in the + * lower-right-hand corner of the on-screen data import dialog box when pane is installed. + * If mode is ButtonMode.CLOSE, the button will have the title "Close." If mode is + * ButtonMode.CANCEL, the button will be titled "Cancel." You should set mode depending on + * whether a cancellable action is in progress. For example, if your importer is in the + * middle of processing 3 of 8 videos, then mode should be ButtonMode.CANCEL. However, if + * the processing operation has completed and the success pane is displayed, then mode + * should be ButtonMode.CLOSE, because all cancellable actions have already + * occurred. + */ + public abstract void install_static_message_pane(string message, + ButtonMode mode = ButtonMode.CANCEL); + + /** + * Attempts to install a library selection pane that presents a list of + * discovered libraries to the user. + * + * When the user clicks the “OK” button, you’ll be notified of the user’s action through + * the 'on_library_selected' callback if a discovered library was selected or through + * the 'on_file_selected' callback if a file was selected. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param welcome_message the text to be displayed above the list of discovered + * libraries. + * + * @param discovered_libraries the list of importable libraries that the plugin + * has discovered in well known locations. + * + * @param file_select_label the label to display for the file selection + * option. If this label is null, the + * user will not be presented with a file selection option. + */ + public abstract void install_library_selection_pane( + string welcome_message, + ImportableLibrary[] discovered_libraries, + string? file_select_label + ); + + /** + * Attempts to install a progress pane that provides the user with feedback + * on import preparation. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param message the text to be displayed above the progress bar. + */ + public abstract void install_import_progress_pane( + string message + ); + + /** + * Update the progress bar installed by install_import_progress_pane. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param progress a value between 0.0 and 1.0 identifying progress for the + * plugin. + * + * @param progress_label the text to be displayed below the progress bar. If that + * parameter is null, the message will be left unchanged. + */ + public abstract void update_import_progress_pane( + double progress, + string? progress_message = null + ); + + /** + * Sends an importable media item to the host in order to prepare it for import + * and update the progress bar installed by install_import_progress_pane. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param item the importable media item to prepare for import. + * + * @param progress a value between 0.0 and 1.0 identifying progress for the + * plugin. + * + * @param host_progress_delta the amount of progress the host should update + * the progress bar during import preparation. Plugins should ensure that + * a proportion of progress for each media item is set aside for the host + * in oder to ensure a smoother update to the progress bar. + * + * @param progress_message the text to be displayed below the progress bar. If that + * parameter is null, the message will be left unchanged. + */ + public abstract void prepare_media_items_for_import( + ImportableMediaItem[] items, + double progress, + double host_progress_delta = 0.0, + string? progress_message = null + ); + + /** + * Finalize the import sequence for the plugin. This tells the host that + * all media items have been processed and that the plugin has finished all + * import work. Once this method has been called, all resources used by the + * plugin for import should be released and the plugin should be back to the + * state it had just after running the start method. The host will then display + * the final message and show progress as fully complete. In a standard import + * scenario, the user is expected to click the Close button to dismiss the + * dialog. On first run, the host may call the LibrarySelectedCallback again + * to import another library handled by the same plugin. + * + * If an error has posted, the {@link PluginHost} will not honor this request. + * + * @param finalize_message the text to be displayed below the progress bar. If that + * parameter is null, the message will be left unchanged. + */ + public abstract void finalize_import( + ImportedItemsCountCallback report_imported_items_count, + string? finalize_message = null + ); + + // + // For future expansion. + // + protected virtual void reserved0() {} + protected virtual void reserved1() {} + protected virtual void reserved2() {} + protected virtual void reserved3() {} + protected virtual void reserved4() {} + protected virtual void reserved5() {} + protected virtual void reserved6() {} + protected virtual void reserved7() {} +} + +/** + * Describes the features and capabilities of a data import service. + * + * Developers of data import plugins provide a class that implements this interface. + */ +public interface Service : Object, Spit.Pluggable { + /** + * A factory method that instantiates and returns a new {@link DataImporter} object + * that this Service describes. + */ + public abstract Spit.DataImports.DataImporter create_data_importer(Spit.DataImports.PluginHost host); + + // + // For future expansion. + // + protected virtual void reserved0() {} + protected virtual void reserved1() {} + protected virtual void reserved2() {} + protected virtual void reserved3() {} + protected virtual void reserved4() {} + protected virtual void reserved5() {} + protected virtual void reserved6() {} + protected virtual void reserved7() {} +} + +} + diff -Nru shotwell-0.11.91/src/plugins/ManifestWidget.vala shotwell-0.11.92/src/plugins/ManifestWidget.vala --- shotwell-0.11.91/src/plugins/ManifestWidget.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/ManifestWidget.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/plugins/mk/interfaces.mk shotwell-0.11.92/src/plugins/mk/interfaces.mk --- shotwell-0.11.91/src/plugins/mk/interfaces.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/mk/interfaces.mk 2012-02-20 20:47:27.000000000 +0000 @@ -2,13 +2,15 @@ PLUGIN_INTERFACES := \ src/plugins/SpitInterfaces.vala \ src/plugins/TransitionsInterfaces.vala \ - src/plugins/PublishingInterfaces.vala + src/plugins/PublishingInterfaces.vala \ + src/plugins/DataImportsInterfaces.vala PLUGIN_PKG_REQS := \ gobject-2.0 \ glib-2.0 \ gdk-3.0 \ - gtk+-3.0 + gtk+-3.0 \ + gee-1.0 PLUGIN_VAPI := plugins/shotwell-plugin-dev-1.0.vapi PLUGIN_HEADER := $(PLUGIN_VAPI:.vapi=.h) diff -Nru shotwell-0.11.91/src/plugins/mk/plugins.mk shotwell-0.11.92/src/plugins/mk/plugins.mk --- shotwell-0.11.91/src/plugins/mk/plugins.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/mk/plugins.mk 2012-02-20 20:47:27.000000000 +0000 @@ -15,7 +15,8 @@ SpitInterfaces.vala \ TransitionsInterfaces.vala \ StandardHostInterface.vala \ - ManifestWidget.vala + ManifestWidget.vala \ + DataImportsInterfaces.vala # Any unit this unit relies upon (and should be initialized before it's initialized) should # be listed here using its Vala namespace. diff -Nru shotwell-0.11.91/src/plugins/Plugins.vala shotwell-0.11.92/src/plugins/Plugins.vala --- shotwell-0.11.91/src/plugins/Plugins.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/Plugins.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/plugins/PublishingInterfaces.vala shotwell-0.11.92/src/plugins/PublishingInterfaces.vala --- shotwell-0.11.91/src/plugins/PublishingInterfaces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/PublishingInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/plugins/SpitInterfaces.vala shotwell-0.11.92/src/plugins/SpitInterfaces.vala --- shotwell-0.11.91/src/plugins/SpitInterfaces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/SpitInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/plugins/StandardHostInterface.vala shotwell-0.11.92/src/plugins/StandardHostInterface.vala --- shotwell-0.11.91/src/plugins/StandardHostInterface.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/StandardHostInterface.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/plugins/TransitionsInterfaces.vala shotwell-0.11.92/src/plugins/TransitionsInterfaces.vala --- shotwell-0.11.91/src/plugins/TransitionsInterfaces.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/plugins/TransitionsInterfaces.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -89,10 +89,10 @@ /** * Returns the background color of the viewport. */ - public Gdk.Color bg_color { get; private set; } + public Gdk.RGBA bg_color { get; private set; } public Visuals(Gdk.Pixbuf? from_pixbuf, Gdk.Rectangle from_pos, Gdk.Pixbuf? to_pixbuf, - Gdk.Rectangle to_pos, Gdk.Color bg_color) { + Gdk.Rectangle to_pos, Gdk.RGBA bg_color) { this.from_pixbuf = from_pixbuf; this.from_pos = from_pos; this.to_pixbuf = to_pixbuf; diff -Nru shotwell-0.11.91/src/Printing.vala shotwell-0.11.92/src/Printing.vala --- shotwell-0.11.91/src/Printing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Printing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -536,7 +536,7 @@ } private void on_ppi_entry_insert_text(Gtk.Editable editable, string text, int length, - void *position) { + ref int position) { Gtk.Entry sender = (Gtk.Entry) editable; if (is_text_insertion_in_progress) @@ -554,7 +554,7 @@ } if (new_text.length > 0) - sender.insert_text(new_text, (int) new_text.length, position); + sender.insert_text(new_text, (int) new_text.length, ref position); Signal.stop_emission_by_name(sender, "insert-text"); @@ -616,7 +616,9 @@ return Measurement(double.parse(custom_height_entry.get_text()), get_user_unit_choice()); } - private void on_entry_insert_text(Gtk.Editable editable, string text, int length, void *position) { + private void on_entry_insert_text(Gtk.Editable editable, string text, int length, + ref int position) { + Gtk.Entry sender = (Gtk.Entry) editable; if (is_text_insertion_in_progress) @@ -640,7 +642,7 @@ } if (new_text.length > 0) - sender.insert_text(new_text, (int) new_text.length, position); + sender.insert_text(new_text, (int) new_text.length, ref position); Signal.stop_emission_by_name(sender, "insert-text"); diff -Nru shotwell-0.11.91/src/Properties.vala shotwell-0.11.92/src/Properties.vala --- shotwell-0.11.91/src/Properties.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Properties.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/publishing/APIGlue.vala shotwell-0.11.92/src/publishing/APIGlue.vala --- shotwell-0.11.91/src/publishing/APIGlue.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/publishing/APIGlue.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/publishing/PublishingPluginHost.vala shotwell-0.11.92/src/publishing/PublishingPluginHost.vala --- shotwell-0.11.91/src/publishing/PublishingPluginHost.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/publishing/PublishingPluginHost.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/publishing/PublishingUI.vala shotwell-0.11.92/src/publishing/PublishingUI.vala --- shotwell-0.11.91/src/publishing/PublishingUI.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/publishing/PublishingUI.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/publishing/Publishing.vala shotwell-0.11.92/src/publishing/Publishing.vala --- shotwell-0.11.91/src/publishing/Publishing.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/publishing/Publishing.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Resources.vala shotwell-0.11.92/src/Resources.vala --- shotwell-0.11.91/src/Resources.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Resources.vala 2012-02-20 22:59:53.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -15,7 +15,7 @@ public const string APP_LIBRARY_ROLE = _("Photo Manager"); public const string APP_DIRECT_ROLE = _("Photo Viewer"); public const string APP_VERSION = _VERSION; - public const string COPYRIGHT = _("Copyright 2009-2011 Yorba Foundation"); + public const string COPYRIGHT = _("Copyright 2009-2012 Yorba Foundation"); public const string APP_GETTEXT_PACKAGE = GETTEXT_PACKAGE; public const string YORBA_URL = "http://www.yorba.org"; @@ -60,6 +60,7 @@ public const string HFLIP = "object-flip-horizontal"; public const string VFLIP = "object-flip-vertical"; public const string CROP = "shotwell-crop"; + public const string STRAIGHTEN = "shotwell-straighten"; public const string REDEYE = "shotwell-redeye"; public const string ADJUST = "shotwell-adjust"; public const string PIN_TOOLBAR = "shotwell-pin-toolbar"; @@ -156,7 +157,7 @@ public const string STRAIGHTEN_MENU = _("_Straighten"); public const string STRAIGHTEN_LABEL = _("Straighten"); - public const string STRAIGHTEN_TOOLTIP = _("Straightens the photo"); + public const string STRAIGHTEN_TOOLTIP = _("Straighten the photo"); public const string RED_EYE_MENU = _("_Red-eye"); public const string RED_EYE_LABEL = _("Red-eye"); @@ -690,6 +691,7 @@ add_stock_icon(icons_dir.get_child("pin-toolbar.svg"), PIN_TOOLBAR); add_stock_icon(icons_dir.get_child("make-primary.svg"), MAKE_PRIMARY); add_stock_icon(icons_dir.get_child("import.svg"), IMPORT); + add_stock_icon(icons_dir.get_child("straighten.svg"), STRAIGHTEN); add_stock_icon(icons_dir.get_child("import-all.png"), IMPORT_ALL); add_stock_icon(icons_dir.get_child("enhance.png"), ENHANCE); add_stock_icon(icons_dir.get_child("crop-pivot-reticle.png"), CROP_PIVOT_RETICLE); @@ -898,10 +900,10 @@ } } - public string to_css_color(Gdk.Color color) { - int r = (int) ((((double) color.red) / uint16.MAX) * 255); - int g = (int) ((((double) color.green) / uint16.MAX) * 255); - int b = (int) ((((double) color.blue) / uint16.MAX) * 255); + public string to_css_color(Gdk.RGBA color) { + int r = (int) (color.red * 255); + int g = (int) (color.green * 255); + int b = (int) (color.blue * 255); return "rgb(%d, %d, %d)".printf(r, g, b); } @@ -943,7 +945,7 @@ public const string INSET_FRAME_STYLESHEET = """ .frame { border-style: inset; - border-width: 1; + border-width: 1px; }"""; public const string SCROLL_FRAME_STYLESHEET = @@ -955,13 +957,13 @@ } .frame { - border-width: 1; + border-width: 1px; border-style: inset; }"""; public const string PAGE_STYLESHEET = """ .frame { - border-width: 1; + border-width: 1px; border-style: inset; border-radius: 0; @@ -970,7 +972,7 @@ public const string VIEWPORT_STYLESHEET = """ GtkViewport { - border-width: 1; + border-width: 1px; border-style: inset; border-radius: 0; padding: 0; @@ -982,7 +984,7 @@ .toolbar { background-color: @primary-bg; - border-width: 1; + border-width: 1px; border-color: shade (@primary-bg, 0.75); border-style: solid; }"""; @@ -996,7 +998,7 @@ background-color: @primary-bg; border-image: none; border-style: none; - margin: 5; + margin: 5px; -unico-border-gradient: none; -unico-outer-stroke-width: 0; @@ -1008,13 +1010,13 @@ .button:prelight { border-style: solid; - border-width: 1; + border-width: 1px; border-color: shade (@primary-bg, 1.1); -unico-inner-stroke-color: shade (@primary-bg, 1.1); -unico-inner-stroke-width: 0; - -unico-outer-stroke-width: 1; + -unico-outer-stroke-width: 1px; -unico-outer-stroke-color: shade (@primary-bg, 0.8); } @@ -1022,10 +1024,10 @@ background-image: none; background-color: shade (@primary-bg, 0.75); border-style: solid; - border-width: 1; + border-width: 1px; border-color: shade (@primary-bg, 0.6); - -unico-outer-stroke-width: 1; + -unico-outer-stroke-width: 1px; -unico-outer-stroke-color: shade (@primary-bg, 1.1); }"""; } diff -Nru shotwell-0.11.91/src/Screensaver.vala shotwell-0.11.92/src/Screensaver.vala --- shotwell-0.11.91/src/Screensaver.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Screensaver.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/searches/Branch.vala shotwell-0.11.92/src/searches/Branch.vala --- shotwell-0.11.91/src/searches/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/searches/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/searches/SavedSearchDialog.vala shotwell-0.11.92/src/searches/SavedSearchDialog.vala --- shotwell-0.11.91/src/searches/SavedSearchDialog.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/searches/SavedSearchDialog.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/searches/SavedSearchPage.vala shotwell-0.11.92/src/searches/SavedSearchPage.vala --- shotwell-0.11.91/src/searches/SavedSearchPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/searches/SavedSearchPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/searches/SearchBoolean.vala shotwell-0.11.92/src/searches/SearchBoolean.vala --- shotwell-0.11.91/src/searches/SearchBoolean.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/searches/SearchBoolean.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -652,7 +652,8 @@ return (dt.compare(date_one) <= 0); case Context.BETWEEN: - return (dt.compare(date_one) >= 0 && dt.compare(date_two) < 0); + DateTime second = date_two.add_days(1); + return (dt.compare(date_one) >= 0 && dt.compare(second) < 0); case Context.IS_NOT_SET: return false; // Already checked above. diff -Nru shotwell-0.11.91/src/searches/Searches.vala shotwell-0.11.92/src/searches/Searches.vala --- shotwell-0.11.91/src/searches/Searches.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/searches/Searches.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/SearchFilter.vala shotwell-0.11.92/src/SearchFilter.vala --- shotwell-0.11.91/src/SearchFilter.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/SearchFilter.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -733,8 +733,8 @@ } } - public void set_color(Gdk.Color color) { - label.modify_fg(Gtk.StateType.NORMAL, color); + public void set_color(Gdk.RGBA color) { + label.override_color(Gtk.StateFlags.NORMAL, color); } } diff -Nru shotwell-0.11.91/src/sidebar/Branch.vala shotwell-0.11.92/src/sidebar/Branch.vala --- shotwell-0.11.91/src/sidebar/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/sidebar/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/sidebar/common.vala shotwell-0.11.92/src/sidebar/common.vala --- shotwell-0.11.91/src/sidebar/common.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/sidebar/common.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/sidebar/Entry.vala shotwell-0.11.92/src/sidebar/Entry.vala --- shotwell-0.11.91/src/sidebar/Entry.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/sidebar/Entry.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/sidebar/Sidebar.vala shotwell-0.11.92/src/sidebar/Sidebar.vala --- shotwell-0.11.91/src/sidebar/Sidebar.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/sidebar/Sidebar.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/sidebar/Tree.vala shotwell-0.11.92/src/sidebar/Tree.vala --- shotwell-0.11.91/src/sidebar/Tree.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/sidebar/Tree.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -817,7 +817,8 @@ private Gtk.TreePath? get_path_from_event(Gdk.EventButton event) { int x, y; Gdk.ModifierType mask; - event.window.get_pointer(out x, out y, out mask); + event.window.get_device_position(Gdk.Display.get_default().get_device_manager(). + get_client_pointer(), out x, out y, out mask); int cell_x, cell_y; Gtk.TreePath path; diff -Nru shotwell-0.11.91/src/slideshow/Slideshow.vala shotwell-0.11.92/src/slideshow/Slideshow.vala --- shotwell-0.11.91/src/slideshow/Slideshow.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/slideshow/Slideshow.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/slideshow/TransitionEffects.vala shotwell-0.11.92/src/slideshow/TransitionEffects.vala --- shotwell-0.11.91/src/slideshow/TransitionEffects.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/slideshow/TransitionEffects.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright 2010 Maxim Kartashev - * Copyright 2011 Yorba Foundation + * Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -231,7 +231,8 @@ ctx.save(); if (effect.needs_clear_background()) { - Gdk.cairo_set_source_color(ctx, visuals.bg_color); + ctx.set_source_rgba(visuals.bg_color.red, visuals.bg_color.green, visuals.bg_color.blue, + visuals.bg_color.alpha); ctx.rectangle(0, 0, width, height); ctx.fill(); } diff -Nru shotwell-0.11.91/src/SlideshowPage.vala shotwell-0.11.92/src/SlideshowPage.vala --- shotwell-0.11.91/src/SlideshowPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/SlideshowPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/SortedListTests.vala shotwell-0.11.92/src/SortedListTests.vala --- shotwell-0.11.91/src/SortedListTests.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/SortedListTests.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/SortedList.vala shotwell-0.11.92/src/SortedList.vala --- shotwell-0.11.91/src/SortedList.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/SortedList.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/tags/Branch.vala shotwell-0.11.92/src/tags/Branch.vala --- shotwell-0.11.91/src/tags/Branch.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/tags/Branch.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/tags/HierarchicalTagIndex.vala shotwell-0.11.92/src/tags/HierarchicalTagIndex.vala --- shotwell-0.11.91/src/tags/HierarchicalTagIndex.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/tags/HierarchicalTagIndex.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/tags/HierarchicalTagUtilities.vala shotwell-0.11.92/src/tags/HierarchicalTagUtilities.vala --- shotwell-0.11.91/src/tags/HierarchicalTagUtilities.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/tags/HierarchicalTagUtilities.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/tags/TagPage.vala shotwell-0.11.92/src/tags/TagPage.vala --- shotwell-0.11.91/src/tags/TagPage.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/tags/TagPage.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/tags/Tags.vala shotwell-0.11.92/src/tags/Tags.vala --- shotwell-0.11.91/src/tags/Tags.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/tags/Tags.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Tag.vala shotwell-0.11.92/src/Tag.vala --- shotwell-0.11.91/src/Tag.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Tag.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/threads/BackgroundJob.vala shotwell-0.11.92/src/threads/BackgroundJob.vala --- shotwell-0.11.91/src/threads/BackgroundJob.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/threads/BackgroundJob.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/threads/Semaphore.vala shotwell-0.11.92/src/threads/Semaphore.vala --- shotwell-0.11.91/src/threads/Semaphore.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/threads/Semaphore.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/threads/Threads.vala shotwell-0.11.92/src/threads/Threads.vala --- shotwell-0.11.91/src/threads/Threads.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/threads/Threads.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/threads/Workers.vala shotwell-0.11.92/src/threads/Workers.vala --- shotwell-0.11.91/src/threads/Workers.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/threads/Workers.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/ThumbnailCache.vala shotwell-0.11.92/src/ThumbnailCache.vala --- shotwell-0.11.91/src/ThumbnailCache.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/ThumbnailCache.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Thumbnail.vala shotwell-0.11.92/src/Thumbnail.vala --- shotwell-0.11.91/src/Thumbnail.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Thumbnail.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/TimedQueue.vala shotwell-0.11.92/src/TimedQueue.vala --- shotwell-0.11.91/src/TimedQueue.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/TimedQueue.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Tombstone.vala shotwell-0.11.92/src/Tombstone.vala --- shotwell-0.11.91/src/Tombstone.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Tombstone.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -117,7 +117,7 @@ // as not present, and not some other problem (which may be intermittant) if (info == null) { try { - info = yield file.query_info_async(FILE_ATTRIBUTE_STANDARD_NAME, + info = yield file.query_info_async(FileAttribute.STANDARD_NAME, FileQueryInfoFlags.NOFOLLOW_SYMLINKS, Priority.LOW, cancellable); } catch (Error err) { // watch for cancellation, which signals it's time to go diff -Nru shotwell-0.11.91/src/unit/rc/template.vala shotwell-0.11.92/src/unit/rc/template.vala --- shotwell-0.11.91/src/unit/rc/template.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/unit/rc/template.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/unit/rc/UnitInternals.m4 shotwell-0.11.92/src/unit/rc/UnitInternals.m4 --- shotwell-0.11.91/src/unit/rc/UnitInternals.m4 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/unit/rc/UnitInternals.m4 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/unit/rc/unitize_entry.m4 shotwell-0.11.92/src/unit/rc/unitize_entry.m4 --- shotwell-0.11.91/src/unit/rc/unitize_entry.m4 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/unit/rc/unitize_entry.m4 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/unit/rc/Unit.m4 shotwell-0.11.92/src/unit/rc/Unit.m4 --- shotwell-0.11.91/src/unit/rc/Unit.m4 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/unit/rc/Unit.m4 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/unit/Unit.vala shotwell-0.11.92/src/unit/Unit.vala --- shotwell-0.11.91/src/unit/Unit.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/unit/Unit.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/Upgrades.vala shotwell-0.11.92/src/Upgrades.vala --- shotwell-0.11.91/src/Upgrades.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/Upgrades.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/util/file.vala shotwell-0.11.92/src/util/file.vala --- shotwell-0.11.91/src/util/file.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/file.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. @@ -79,7 +79,7 @@ if (type == FileType.REGULAR) { FileInfo info = null; try { - info = file_or_dir.query_info(FILE_ATTRIBUTE_STANDARD_SIZE, + info = file_or_dir.query_info(FileAttribute.STANDARD_SIZE, FileQueryInfoFlags.NOFOLLOW_SYMLINKS, cancellable); } catch (Error err) { if (err is IOError.CANCELLED) @@ -97,7 +97,7 @@ FileEnumerator enumerator; try { - enumerator = file_or_dir.enumerate_children(FILE_ATTRIBUTE_STANDARD_NAME, + enumerator = file_or_dir.enumerate_children(FileAttribute.STANDARD_NAME, FileQueryInfoFlags.NOFOLLOW_SYMLINKS, cancellable); if (enumerator == null) return 0; @@ -152,13 +152,10 @@ } public time_t query_file_modified(File file) throws Error { - FileInfo info = file.query_info(FILE_ATTRIBUTE_TIME_MODIFIED, FileQueryInfoFlags.NOFOLLOW_SYMLINKS, + FileInfo info = file.query_info(FileAttribute.TIME_MODIFIED, FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null); - TimeVal timestamp = TimeVal(); - info.get_modification_time(out timestamp); - - return timestamp.tv_sec; + return info.get_modification_time().tv_sec; } public bool query_is_directory(File file) { @@ -199,7 +196,7 @@ } public string? get_file_info_id(FileInfo info) { - return info.get_attribute_string(FILE_ATTRIBUTE_ID_FILE); + return info.get_attribute_string(FileAttribute.ID_FILE); } // Breaks a uint64 skip amount into several smaller skips. @@ -232,3 +229,18 @@ return count; } +// Replacement for deprecated Gio.file_equal +public bool file_equal(void* _a, void* _b) { + File? a = _a as File; + File? b = _b as File; + + return (a != null && b != null) ? a.equal(b) : false; +} + +// Replacement for deprecated Gio.file_hash +public uint file_hash(void* _file) { + File? file = _file as File; + + return file != null ? file.hash() : 0; +} + diff -Nru shotwell-0.11.91/src/util/image.vala shotwell-0.11.92/src/util/image.vala --- shotwell-0.11.91/src/util/image.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/image.vala 2012-02-20 20:47:45.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -9,21 +9,21 @@ return Gdk.Color.parse(spec, out color); } -Gdk.Color parse_color(string spec) { +Gdk.RGBA parse_color(string spec) { return fetch_color(spec); } -Gdk.Color fetch_color(string spec) { - Gdk.Color color; - if (!Gdk.Color.parse(spec, out color)) +Gdk.RGBA fetch_color(string spec) { + Gdk.RGBA rgba = Gdk.RGBA(); + if (!rgba.parse(spec)) error("Can't parse color %s", spec); - - return color; + + return rgba; } -void set_source_color_with_alpha(Cairo.Context ctx, Gdk.Color color, double alpha) { - ctx.set_source_rgba((double) color.red / 65535.0, (double) color.green / 65535.0, - (double) color.blue / 65535.0, alpha); +void set_source_color_from_string(Cairo.Context ctx, string spec) { + Gdk.RGBA rgba = fetch_color(spec); + ctx.set_source_rgb(rgba.red, rgba.green, rgba.blue); } private const int MIN_SCALED_WIDTH = 10; @@ -136,24 +136,6 @@ return (x >= rect.x && x < (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.height)); } -Gdk.Point coord_scaled_in_space(int x, int y, Dimensions original, Dimensions scaled) { - double x_scale, y_scale; - original.get_scale_ratios(scaled, out x_scale, out y_scale); - - Gdk.Point point = Gdk.Point(); - point.x = (int) Math.round(x * x_scale); - point.y = (int) Math.round(y * y_scale); - - // watch for rounding errors - if (point.x >= scaled.width) - point.x = scaled.width - 1; - - if (point.y >= scaled.height) - point.y = scaled.height - 1; - - return point; -} - public bool rectangles_equal(Gdk.Rectangle a, Gdk.Rectangle b) { return (a.x == b.x) && (a.y == b.y) && (a.width == b.width) && (a.height == b.height); } @@ -172,20 +154,6 @@ return rect; } -// Can only scale a radius when the scale is proportional; returns -1 if not. Only two points of -// precision are considered here. -int radius_scaled_in_space(int radius, Dimensions original, Dimensions scaled) { - double x_scale, y_scale; - original.get_scale_ratios(scaled, out x_scale, out y_scale); - - // using floor() or round() both present problems, since the two values could straddle any FP - // boundary ... instead, look for a reasonable delta - if (Math.fabs(x_scale - y_scale) > 1.0) - return -1; - - return (int) Math.round(radius * x_scale); -} - public Gdk.Point scale_point(Gdk.Point p, double factor) { Gdk.Point result = {0}; result.x = (int) (factor * p.x + 0.5); @@ -235,9 +203,31 @@ } } -// Rotates a pixbuf to an arbitrary angle, given in degrees, and returns the rotated -// pixbuf, cropped to maintain the aspect ratio of the original. -// The caller is responsible for destroying and/or un-reffing the returned pixbuf after use. +/** + * Finds the size of the smallest axially-aligned rectangle that could contain + * a rectangle src_width by src_height, rotated by angle. + * + * @param src_width The width of the incoming rectangle. + * @param src_height The height of the incoming rectangle. + * @param angle The amount to rotate by, given in degrees. + * @param dest_width The width of the computed rectangle. + * @param dest_height The height of the computed rectangle. + */ +void compute_arb_rotated_size(double src_width, double src_height, double angle, + out double dest_width, out double dest_height) { + + angle = Math.fabs(degrees_to_radians(angle)); + assert(angle <= Math.PI_2); + dest_width = src_width * Math.cos(angle) + src_height * Math.sin(angle); + dest_height = src_height * Math.cos(angle) + src_width * Math.sin(angle); +} + +/** + * @brief Rotates a pixbuf to an arbitrary angle, given in degrees, and returns the rotated pixbuf. + * + * @param source_pixbuf The source image that needs to be angled. + * @param angle The angle the source image should be rotated by. + */ Gdk.Pixbuf rotate_arb(Gdk.Pixbuf source_pixbuf, double angle) { // if the straightening angle has been reset // or was never set in the first place, nothing @@ -246,56 +236,35 @@ return source_pixbuf; } - angle = degrees_to_radians(angle); - - // compute how much we'll have to resize (_not_ scale) the - // image by to maintain the aspect ratio with the current angle. - double shrink_factor; - - if (source_pixbuf.width > source_pixbuf.height) { - shrink_factor = 1.0 + (Math.fabs(Math.sin(angle)) * - ((double)source_pixbuf.width / (double)source_pixbuf.height)); - } else { - shrink_factor = 1.0 + (Math.fabs(Math.sin(angle)) * - ((double)source_pixbuf.height / (double)source_pixbuf.width)); - } - - // create the output image with the same aspect ratio, but - // appropriately shrunken size. - double w_tmp = source_pixbuf.width / shrink_factor; - double h_tmp = source_pixbuf.height / shrink_factor; - - Gdk.Pixbuf dest_pixbuf = new Gdk.Pixbuf(Gdk.Colorspace.RGB, true, 8, (int) w_tmp, (int) h_tmp); - - Cairo.ImageSurface surface; - - if(source_pixbuf.has_alpha) { - surface = new Cairo.ImageSurface.for_data( - (uchar []) dest_pixbuf.pixels, Cairo.Format.ARGB32, - dest_pixbuf.width, dest_pixbuf.height, dest_pixbuf.rowstride); - } else { - surface = new Cairo.ImageSurface.for_data( - (uchar []) dest_pixbuf.pixels, Cairo.Format.RGB24, - dest_pixbuf.width, dest_pixbuf.height, dest_pixbuf.rowstride); - } + // Compute how much the corners of the source image will + // move by to determine how big the dest pixbuf should be. + double x_tmp, y_tmp; + compute_arb_rotated_size(source_pixbuf.width, source_pixbuf.height, angle, + out x_tmp, out y_tmp); + + Gdk.Pixbuf dest_pixbuf = new Gdk.Pixbuf( + Gdk.Colorspace.RGB, true, 8, (int) Math.round(x_tmp), (int) Math.round(y_tmp)); + + Cairo.ImageSurface surface = new Cairo.ImageSurface.for_data( + (uchar []) dest_pixbuf.pixels, + source_pixbuf.has_alpha ? Cairo.Format.ARGB32 : Cairo.Format.RGB24, + dest_pixbuf.width, dest_pixbuf.height, dest_pixbuf.rowstride); + Cairo.Context context = new Cairo.Context(surface); - - // actually draw the source image, at an angle, onto - // the destination one, along with appropriate translations - // to make sure it stays centered. + context.set_source_rgb(0, 0, 0); context.rectangle(0, 0, dest_pixbuf.width, dest_pixbuf.height); context.fill(); - - context.translate(w_tmp / 2.0, h_tmp / 2.0); - context.rotate(angle); - context.translate(-source_pixbuf.width / 2.0, -source_pixbuf.height / 2.0); - + + context.translate(dest_pixbuf.width / 2, dest_pixbuf.height / 2); + context.rotate(degrees_to_radians(angle)); + context.translate(- source_pixbuf.width / 2, - source_pixbuf.height / 2); + Gdk.cairo_set_source_pixbuf(context, source_pixbuf, 0, 0); context.get_source().set_filter(Cairo.Filter.BEST); context.paint(); - + // prepare the newly-drawn image for use by // the rest of the pipeline. fix_cairo_pixbuf(dest_pixbuf); @@ -303,42 +272,93 @@ return dest_pixbuf; } -// Rotates a point around the center of an image to an arbitrary angle, given in degrees, -// and returns the rotated point, using computations similar to rotate_arb()'s. -// Needed primarily for the redeye tool. -Gdk.Point rotate_point_arb(Gdk.Point source_point, int img_w, int img_h, double angle) { +/** + * @brief Rotates a point around the upper left corner of an image to an arbitrary angle, + * given in degrees, and returns the rotated point, translated such that it, along with its attendant + * image, are in positive x, positive y. + * + * @note May be subject to slight inaccuracy as Gdk points' coordinates may only be in whole pixels, + * so the fractional component is lost. + * + * @param source_point The point to be rotated and scaled. + * @param img_w The width of the source image (unrotated). + * @param img_h The height of the source image (unrotated). + * @param angle The angle the source image is to be rotated by to straighten it. + */ +Gdk.Point rotate_point_arb(Gdk.Point source_point, int img_w, int img_h, double angle, + bool invert = false) { // angle of 0 degrees or angle was never set? if (angle == 0.0) { // nothing needs to be done. return source_point; } - angle = degrees_to_radians(angle); + double dest_width; + double dest_height; + compute_arb_rotated_size(img_w, img_h, angle, out dest_width, out dest_height); + + Cairo.Matrix matrix = new Cairo.Matrix.identity(); + matrix.translate(dest_width / 2, dest_height / 2); + matrix.rotate(degrees_to_radians(angle)); + matrix.translate(- img_w / 2, - img_h / 2); + if (invert) + assert(matrix.invert() == Cairo.Status.SUCCESS); + + double dest_x = source_point.x; + double dest_y = source_point.y; + matrix.transform_point(ref dest_x, ref dest_y); + + return { (int) dest_x, (int) dest_y }; +} + +/** + * @brief Derotates a point around the upper left corner of an image from an arbitrary angle, + * given in degrees, and returns the de-rotated point, taking into account any translation necessary + * to make sure all of the rotated image stays in positive x, positive y. + * + * @note May be subject to slight inaccuracy as Gdk points' coordinates may only be in whole pixels, + * so the fractional component is lost. + * + * @param source_point The point to be de-rotated. + * @param img_w The width of the source image (unrotated). + * @param img_h The height of the source image (unrotated). + * @param angle The angle the source image is to be rotated by to straighten it. + */ +Gdk.Point derotate_point_arb(Gdk.Point source_point, int img_w, int img_h, double angle) { + return rotate_point_arb(source_point, img_w, img_h, angle, true); +} - double shrink_factor; - if (img_w > img_h) { - shrink_factor = 1.0 + (Math.fabs(Math.sin(angle)) * - ((double) img_w / (double) img_h)); - } else { - shrink_factor = 1.0 + (Math.fabs(Math.sin(angle)) * - ((double) img_h / (double) img_w)); - } +// Force an axially-aligned box to be inside a rotated rectangle. +Box clamp_inside_rotated_image(Box src, int img_w, int img_h, double angle_deg, + bool preserve_geom) { - double dest_x_tmp = (source_point.x - (img_w / 2.0)) / shrink_factor; - double dest_y_tmp = (source_point.y - (img_h / 2.0)) / shrink_factor; - double rot_tmp = dest_x_tmp; + Gdk.Point top_left = derotate_point_arb({src.left, src.top}, img_w, img_h, angle_deg); + Gdk.Point top_right = derotate_point_arb({src.right, src.top}, img_w, img_h, angle_deg); + Gdk.Point bottom_left = derotate_point_arb({src.left, src.bottom}, img_w, img_h, angle_deg); + Gdk.Point bottom_right = derotate_point_arb({src.right, src.bottom}, img_w, img_h, angle_deg); - dest_x_tmp = (Math.cos(angle * -1.0) * dest_x_tmp) - (Math.sin(angle * -1.0) * dest_y_tmp); - dest_y_tmp = (Math.sin(angle * -1.0) * rot_tmp) + (Math.cos(angle * -1.0) * dest_y_tmp); + double angle = degrees_to_radians(angle_deg); + int top_offset = 0, bottom_offset = 0, left_offset = 0, right_offset = 0; - dest_x_tmp += (img_w / 2.0); - dest_y_tmp += (img_h / 2.0); - - Gdk.Point dest_point = Gdk.Point(); - dest_point.x = (int) dest_x_tmp; - dest_point.y = (int) dest_y_tmp; - - return dest_point; + int top = int.min(top_left.y, top_right.y); + if (top < 0) + top_offset = (int) ((0 - top) * Math.cos(angle)); + + int bottom = int.max(bottom_left.y, bottom_right.y); + if (bottom > img_h) + bottom_offset = (int) ((img_h - bottom) * Math.cos(angle)); + + int left = int.min(top_left.x, bottom_left.x); + if (left < 0) + left_offset = (int) ((0 - left) * Math.cos(angle)); + + int right = int.max(top_right.x, bottom_right.x); + if (right > img_w) + right_offset = (int) ((img_w - right) * Math.cos(angle)); + + return preserve_geom ? src.get_offset(left_offset + right_offset, top_offset + bottom_offset) + : Box(src.left + left_offset, src.top + top_offset, + src.right + right_offset, src.bottom + bottom_offset); } - + diff -Nru shotwell-0.11.91/src/util/KeyValueMap.vala shotwell-0.11.92/src/util/KeyValueMap.vala --- shotwell-0.11.91/src/util/KeyValueMap.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/KeyValueMap.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/util/misc.vala shotwell-0.11.92/src/util/misc.vala --- shotwell-0.11.91/src/util/misc.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/misc.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -354,6 +354,16 @@ } } +// Dummy function for suppressing 'could not stat file' errors +// generated when saving into a previously non-existant file - +// please see https://bugzilla.gnome.org/show_bug.cgi?id=662814 +// and to work around a spurious warning given by GDK when a +// key press event is passed from a child class' event handler +// to a parent's; (gnome bug pending, but see https://bugzilla.redhat.com/show_bug.cgi?id=665568). +public void suppress_warnings(string? log_domain, LogLevelFlags log_levels, string message) { + // do nothing. +} + public bool is_twentyfour_hr_time_system() { // if no AM/PM designation is found, the location is set to use a 24 hr time system return is_string_empty(Time.local(0).format("%p")); diff -Nru shotwell-0.11.91/src/util/string.vala shotwell-0.11.92/src/util/string.vala --- shotwell-0.11.91/src/util/string.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/string.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/util/system.vala shotwell-0.11.92/src/util/system.vala --- shotwell-0.11.91/src/util/system.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/system.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/util/ui.vala shotwell-0.11.92/src/util/ui.vala --- shotwell-0.11.91/src/util/ui.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/ui.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/util/Util.vala shotwell-0.11.92/src/util/Util.vala --- shotwell-0.11.91/src/util/Util.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/util/Util.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/VideoMetadata.vala shotwell-0.11.92/src/VideoMetadata.vala --- shotwell-0.11.91/src/VideoMetadata.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/VideoMetadata.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/VideoMonitor.vala shotwell-0.11.92/src/VideoMonitor.vala --- shotwell-0.11.91/src/VideoMonitor.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/VideoMonitor.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/src/VideoSupport.vala shotwell-0.11.92/src/VideoSupport.vala --- shotwell-0.11.91/src/VideoSupport.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/src/VideoSupport.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -83,8 +83,7 @@ return ImportResult.UNSUPPORTED_FORMAT; } - TimeVal timestamp; - info.get_modification_time(out timestamp); + TimeVal timestamp = info.get_modification_time(); // make sure params has a valid md5 assert(params.md5 != null); @@ -405,7 +404,7 @@ if (videos.size == 0) return null; - // in place export is relatively easy -- provide a fast, separate code path for it + // in place export is relatively easy -- provide a fast, separate code path for it if (export_in_place) { ExporterUI temp_exporter = new ExporterUI(new Exporter.for_temp_file(videos, Scaling.for_original(), ExportFormatParameters.unmodified())); @@ -701,7 +700,7 @@ } } - public override Dimensions get_dimensions() { + public override Dimensions get_dimensions(Photo.Exception disallowed_steps = Photo.Exception.NONE) { return get_frame_dimensions(); } @@ -722,8 +721,7 @@ } public void set_master_timestamp(FileInfo info) { - TimeVal time_val; - info.get_modification_time(out time_val); + TimeVal time_val = info.get_modification_time(); try { lock (backing_row) { @@ -1073,10 +1071,7 @@ if (video.get_filesize() != info.get_size()) return; - TimeVal modification; - info.get_modification_time(out modification); - - if (video.get_timestamp() == modification.tv_sec) + if (video.get_timestamp() == info.get_modification_time().tv_sec) matching_master.add(video); } diff -Nru shotwell-0.11.91/THANKS shotwell-0.11.92/THANKS --- shotwell-0.11.91/THANKS 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/THANKS 2012-02-20 20:47:27.000000000 +0000 @@ -27,7 +27,9 @@ Dominic Lloyd Tobias Lott Gavrilov Maksim +Trevor Mehard Rafael Monica +Thomas Moschny Paul Novak Evgeniy Polyakov Siddhesh Poyarekar @@ -39,6 +41,7 @@ Elliott S Michel Alexandre Salim Benedikt Sauer +Peter Seiderer Wolfgang Steitz Marcel Stimberg Vincent Untz diff -Nru shotwell-0.11.91/thumbnailer/shotwell-video-thumbnailer.vala shotwell-0.11.92/thumbnailer/shotwell-video-thumbnailer.vala --- shotwell-0.11.91/thumbnailer/shotwell-video-thumbnailer.vala 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/thumbnailer/shotwell-video-thumbnailer.vala 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2011 Yorba Foundation +/* Copyright 2011-2012 Yorba Foundation * * This is a Vala-rewrite of GStreamer snapshot example. Adapted from earlier * work from Wim Taymans. diff -Nru shotwell-0.11.91/ui/direct.ui shotwell-0.11.92/ui/direct.ui --- shotwell-0.11.91/ui/direct.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/direct.ui 2012-02-20 20:47:27.000000000 +0000 @@ -43,6 +43,7 @@ + diff -Nru shotwell-0.11.91/ui/events_directory.ui shotwell-0.11.92/ui/events_directory.ui --- shotwell-0.11.91/ui/events_directory.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/events_directory.ui 2012-02-20 20:47:27.000000000 +0000 @@ -3,7 +3,7 @@ - + diff -Nru shotwell-0.11.91/ui/import_queue.ui shotwell-0.11.92/ui/import_queue.ui --- shotwell-0.11.91/ui/import_queue.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/import_queue.ui 2012-02-20 20:47:27.000000000 +0000 @@ -5,7 +5,7 @@ - + diff -Nru shotwell-0.11.91/ui/import.ui shotwell-0.11.92/ui/import.ui --- shotwell-0.11.91/ui/import.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/import.ui 2012-02-20 20:47:27.000000000 +0000 @@ -5,7 +5,7 @@ - + diff -Nru shotwell-0.11.91/ui/media.ui shotwell-0.11.92/ui/media.ui --- shotwell-0.11.91/ui/media.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/media.ui 2012-02-20 20:47:27.000000000 +0000 @@ -3,7 +3,7 @@ - + diff -Nru shotwell-0.11.91/ui/offline.ui shotwell-0.11.92/ui/offline.ui --- shotwell-0.11.91/ui/offline.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/offline.ui 2012-02-20 20:47:27.000000000 +0000 @@ -3,7 +3,7 @@ - + diff -Nru shotwell-0.11.91/ui/photo.ui shotwell-0.11.92/ui/photo.ui --- shotwell-0.11.91/ui/photo.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/photo.ui 2012-02-20 20:47:27.000000000 +0000 @@ -3,7 +3,7 @@ - + @@ -66,6 +66,7 @@ + diff -Nru shotwell-0.11.91/ui/shotwell.glade shotwell-0.11.92/ui/shotwell.glade --- shotwell-0.11.91/ui/shotwell.glade 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/shotwell.glade 2012-02-20 20:47:27.000000000 +0000 @@ -202,217 +202,6 @@ - - False - False - True - center-on-parent - True - dialog - - - True - False - - - True - False - 6 - 6 - - - True - False - - - True - False - - - - - - True - True - 0 - - - - - True - False - 20 - - - True - False - - - - - - False - True - 1 - - - - - True - False - 12 - - - True - False - False - False - - - True - False - - - - - - - - True - False - - - True - False - GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK - True - Preparing pictures for import... - - - True - True - 0 - - - - - 1 - - - - - - - - True - False - - - True - False - gtk-dialog-error - - - False - True - 6 - 0 - - - - - True - False - error - - - False - True - 6 - 1 - - - - - 2 - - - - - - - - - - False - True - 2 - - - - - - - True - True - 6 - 0 - - - - - True - False - end - - - gtk-cancel - True - True - True - False - True - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - True - True - True - False - True - - - False - False - 1 - - - - - False - True - end - 1 - - - - - - cancel_button - ok_button - - 65535 1000 diff -Nru shotwell-0.11.91/ui/shotwell.xml shotwell-0.11.92/ui/shotwell.xml --- shotwell-0.11.91/ui/shotwell.xml 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/shotwell.xml 2012-02-20 20:47:27.000000000 +0000 @@ -2,11 +2,9 @@ - - diff -Nru shotwell-0.11.91/ui/trash.ui shotwell-0.11.92/ui/trash.ui --- shotwell-0.11.91/ui/trash.ui 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/ui/trash.ui 2012-02-20 20:47:27.000000000 +0000 @@ -3,7 +3,7 @@ - + diff -Nru shotwell-0.11.91/units.mk shotwell-0.11.92/units.mk --- shotwell-0.11.91/units.mk 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/units.mk 2012-02-20 20:47:27.000000000 +0000 @@ -16,8 +16,6 @@ slideshow \ photos \ publishing \ - alien_db \ - alien_db/f_spot \ library \ direct \ core \ @@ -27,7 +25,8 @@ faces \ camera \ searches \ - config + config \ + data_imports # Name(s) of units that represent application entry points. These units will have init and # termination entry points generated: Name.unitize_init() and Name.unitize_terminate(). These diff -Nru shotwell-0.11.91/vapi/ExtendedPosix.vapi shotwell-0.11.92/vapi/ExtendedPosix.vapi --- shotwell-0.11.91/vapi/ExtendedPosix.vapi 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/ExtendedPosix.vapi 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/vapi/gdk-3.0.vapi shotwell-0.11.92/vapi/gdk-3.0.vapi --- shotwell-0.11.91/vapi/gdk-3.0.vapi 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/gdk-3.0.vapi 1970-01-01 00:00:00.000000000 +0000 @@ -1,1392 +0,0 @@ -/* gdk-3.0.vapi generated by vapigen, do not modify. */ - -[CCode (gir_namespace = "Gdk", gir_version = "3.0")] -namespace Gdk { - namespace Selection { - [CCode (cheader_filename = "gdk/gdk.h")] - public static void convert (Gdk.Window requestor, Gdk.Atom selection, Gdk.Atom target, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.Window owner_get (Gdk.Atom selection); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.Window owner_get_for_display (Gdk.Display display, Gdk.Atom selection); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool owner_set (Gdk.Window owner, Gdk.Atom selection, uint32 time_, bool send_event); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool owner_set_for_display (Gdk.Display display, Gdk.Window owner, Gdk.Atom selection, uint32 time_, bool send_event); - [CCode (cheader_filename = "gdk/gdk.h")] - public static int property_get (Gdk.Window requestor, uchar[] data, out Gdk.Atom prop_type, int prop_format); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void send_notify (Gdk.Window requestor, Gdk.Atom selection, Gdk.Atom target, Gdk.Atom property, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void send_notify_for_display (Gdk.Display display, Gdk.Window requestor, Gdk.Atom selection, Gdk.Atom target, Gdk.Atom property, uint32 time_); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class AppLaunchContext : GLib.AppLaunchContext { - [CCode (has_construct_function = false)] - protected AppLaunchContext (); - public void set_desktop (int desktop); - public void set_icon (GLib.Icon icon); - public void set_icon_name (string icon_name); - public void set_screen (Gdk.Screen screen); - public void set_timestamp (uint32 timestamp); - [NoAccessorMethod] - public Gdk.Display display { owned get; construct; } - } - [CCode (cheader_filename = "gdk/gdk.h", ref_function = "g_object_ref", unref_function = "g_object_unref")] - public class Bitmap { - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Cursor : GLib.Object { - [CCode (has_construct_function = false)] - public Cursor (Gdk.CursorType cursor_type); - [CCode (has_construct_function = false)] - public Cursor.for_display (Gdk.Display display, Gdk.CursorType cursor_type); - [CCode (has_construct_function = false)] - public Cursor.from_name (Gdk.Display display, string name); - [CCode (has_construct_function = false)] - public Cursor.from_pixbuf (Gdk.Display display, Gdk.Pixbuf pixbuf, int x, int y); - public Gdk.CursorType get_cursor_type (); - public unowned Gdk.Display get_display (); - public unowned Gdk.Pixbuf get_image (); - public Gdk.CursorType cursor_type { get; construct; } - public Gdk.Display display { get; construct; } - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Device : GLib.Object { - [CCode (has_construct_function = false)] - protected Device (); - public static void free_history (Gdk.TimeCoord[] events); - public unowned Gdk.Device? get_associated_device (); - public bool get_axis ([CCode (array_length = false)] double[] axes, Gdk.AxisUse use, out double value); - public Gdk.AxisUse get_axis_use (uint index_); - public bool get_axis_value ([CCode (array_length = false)] double[] axes, Gdk.Atom axis_label, out double value); - public Gdk.DeviceType get_device_type (); - public unowned Gdk.Display get_display (); - public bool get_has_cursor (); - public bool get_history (Gdk.Window window, uint32 start, uint32 stop, out Gdk.TimeCoord[] events); - public bool get_key (uint index_, out uint keyval, out Gdk.ModifierType modifiers); - public Gdk.InputMode get_mode (); - public int get_n_axes (); - public int get_n_keys (); - public unowned string get_name (); - public void get_position (out unowned Gdk.Screen screen, out int x, out int y); - public Gdk.InputSource get_source (); - public void get_state (Gdk.Window window, [CCode (array_length = false)] double[] axes, out Gdk.ModifierType mask); - public unowned Gdk.Window? get_window_at_position (int win_x, int win_y); - public Gdk.GrabStatus grab (Gdk.Window window, Gdk.GrabOwnership grab_ownership, bool owner_events, Gdk.EventMask event_mask, Gdk.Cursor? cursor, uint32 time_); - public static bool grab_info_libgtk_only (Gdk.Display display, Gdk.Device device, out unowned Gdk.Window grab_window, bool owner_events); - public GLib.List list_axes (); - public GLib.List? list_slave_devices (); - public void set_axis_use (uint index_, Gdk.AxisUse use); - public void set_key (uint index_, uint keyval, Gdk.ModifierType modifiers); - public bool set_mode (Gdk.InputMode mode); - public void ungrab (uint32 time_); - public void warp (Gdk.Screen screen, int x, int y); - public Gdk.Device? associated_device { get; } - [NoAccessorMethod] - public Gdk.DeviceManager device_manager { owned get; construct; } - public Gdk.Display display { get; construct; } - public bool has_cursor { get; construct; } - [NoAccessorMethod] - public Gdk.InputMode input_mode { get; set; } - [NoAccessorMethod] - public Gdk.InputSource input_source { get; construct; } - public uint n_axes { get; } - public string? name { get; construct; } - [NoAccessorMethod] - public Gdk.DeviceType type { get; construct; } - public virtual signal void changed (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class DeviceManager : GLib.Object { - [CCode (has_construct_function = false)] - protected DeviceManager (); - public unowned Gdk.Device get_client_pointer (); - public unowned Gdk.Display get_display (); - public unowned GLib.List list_devices (Gdk.DeviceType type); - public Gdk.Display display { get; construct; } - public virtual signal void device_added (Gdk.Device p0); - public virtual signal void device_changed (Gdk.Device p0); - public virtual signal void device_removed (Gdk.Device p0); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Display : GLib.Object { - [CCode (has_construct_function = false)] - protected Display (); - public void beep (); - public void close (); - public bool device_is_grabbed (Gdk.Device device); - public void flush (); - public unowned Gdk.AppLaunchContext get_app_launch_context (); - public static unowned Gdk.Display get_default (); - public uint get_default_cursor_size (); - public unowned Gdk.Window get_default_group (); - public unowned Gdk.Screen get_default_screen (); - public unowned Gdk.DeviceManager get_device_manager (); - public Gdk.Event get_event (); - public void get_maximal_cursor_size (out uint width, out uint height); - public int get_n_screens (); - public unowned string get_name (); - public unowned Gdk.Screen get_screen (int screen_num); - public bool has_pending (); - public bool is_closed (); - public void notify_startup_complete (string startup_id); - public static unowned Gdk.Display open (string display_name); - public static unowned Gdk.Display open_default_libgtk_only (); - public Gdk.Event peek_event (); - public void put_event (Gdk.Event event); - public bool request_selection_notification (Gdk.Atom selection); - public void set_double_click_distance (uint distance); - public void set_double_click_time (uint msec); - public void store_clipboard (Gdk.Window clipboard_window, uint32 time_, Gdk.Atom[] targets); - public bool supports_clipboard_persistence (); - public bool supports_composite (); - public bool supports_cursor_alpha (); - public bool supports_cursor_color (); - public bool supports_input_shapes (); - public bool supports_selection_notification (); - public bool supports_shapes (); - public void sync (); - public virtual signal void closed (bool p0); - public virtual signal void opened (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class DisplayManager : GLib.Object { - [CCode (has_construct_function = false)] - protected DisplayManager (); - public static unowned Gdk.DisplayManager @get (); - public unowned Gdk.Display get_default_display (); - public GLib.SList list_displays (); - public unowned Gdk.Display open_display (string name); - public void set_default_display (Gdk.Display display); - public Gdk.Display default_display { get; set; } - public virtual signal void display_opened (Gdk.Display p0); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class DragContext : GLib.Object { - [CCode (has_construct_function = false)] - protected DragContext (); - public Gdk.DragAction get_actions (); - public unowned Gdk.Window get_dest_window (); - public unowned Gdk.Device get_device (); - public Gdk.DragProtocol get_protocol (); - public Gdk.DragAction get_selected_action (); - public unowned Gdk.Window get_source_window (); - public Gdk.DragAction get_suggested_action (); - public unowned GLib.List list_targets (); - public void set_device (Gdk.Device device); - } - [CCode (cheader_filename = "gdk/gdk.h", copy_function = "gdk_event_copy", type_id = "gdk_event_get_type ()")] - [Compact] - public class Event { - public Gdk.EventAny any; - public Gdk.EventButton button; - public Gdk.EventConfigure configure; - public Gdk.EventCrossing crossing; - public Gdk.EventDND dnd; - public Gdk.EventExpose expose; - public Gdk.EventFocus focus_change; - public Gdk.EventGrabBroken grab_broken; - public Gdk.EventKey key; - public Gdk.EventMotion motion; - public Gdk.EventOwnerChange owner_change; - public Gdk.EventProperty property; - public Gdk.EventProximity proximity; - public Gdk.EventScroll scroll; - public Gdk.EventSelection selection; - public Gdk.EventSetting setting; - public Gdk.EventType type; - public Gdk.EventVisibility visibility; - public Gdk.EventWindowState window_state; - [CCode (has_construct_function = false)] - public Event (Gdk.EventType type); - public Gdk.Event copy (); - public static unowned Gdk.Event @get (); - public bool get_axis (Gdk.AxisUse axis_use, out double value); - public bool get_coords (out double x_win, out double y_win); - public unowned Gdk.Device get_device (); - public bool get_root_coords (out double x_root, out double y_root); - public unowned Gdk.Screen get_screen (); - public unowned Gdk.Device get_source_device (); - public bool get_state (out Gdk.ModifierType state); - public uint32 get_time (); - public static void handler_set (owned Gdk.EventFunc func); - public static unowned Gdk.Event peek (); - public void put (); - public static void request_motions (Gdk.EventMotion event); - public void set_device (Gdk.Device device); - public void set_screen (Gdk.Screen screen); - public void set_source_device (Gdk.Device device); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Keymap : GLib.Object { - [CCode (has_construct_function = false)] - protected Keymap (); - public void add_virtual_modifiers (Gdk.ModifierType state); - public bool get_caps_lock_state (); - public static unowned Gdk.Keymap get_default (); - public Pango.Direction get_direction (); - public bool get_entries_for_keycode (uint hardware_keycode, [CCode (array_length = false)] out Gdk.KeymapKey[] keys, [CCode (array_length = false)] out uint[] keyvals, out int n_entries); - public bool get_entries_for_keyval (uint keyval, out unowned Gdk.KeymapKey[] keys); - public static unowned Gdk.Keymap get_for_display (Gdk.Display display); - public bool get_num_lock_state (); - public bool have_bidi_layouts (); - public uint lookup_key (Gdk.KeymapKey key); - public bool map_virtual_modifiers (Gdk.ModifierType state); - public bool translate_keyboard_state (uint hardware_keycode, Gdk.ModifierType state, int group, uint keyval, int effective_group, int level, Gdk.ModifierType consumed_modifiers); - public virtual signal void direction_changed (); - public virtual signal void keys_changed (); - public virtual signal void state_changed (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Screen : GLib.Object { - [CCode (has_construct_function = false)] - protected Screen (); - public unowned Gdk.Window get_active_window (); - public static unowned Gdk.Screen get_default (); - public unowned Gdk.Display get_display (); - public unowned Cairo.FontOptions get_font_options (); - public int get_height (); - public int get_height_mm (); - public int get_monitor_at_point (int x, int y); - public int get_monitor_at_window (Gdk.Window window); - public void get_monitor_geometry (int monitor_num, out Gdk.Rectangle dest); - public int get_monitor_height_mm (int monitor_num); - public unowned string get_monitor_plug_name (int monitor_num); - public int get_monitor_width_mm (int monitor_num); - public int get_n_monitors (); - public int get_number (); - public int get_primary_monitor (); - public double get_resolution (); - public unowned Gdk.Visual get_rgba_visual (); - public unowned Gdk.Window get_root_window (); - public bool get_setting (string name, GLib.Value value); - public unowned Gdk.Visual get_system_visual (); - public GLib.List get_toplevel_windows (); - public int get_width (); - public int get_width_mm (); - public GLib.List? get_window_stack (); - public static int height (); - public static int height_mm (); - public bool is_composited (); - public GLib.List list_visuals (); - public unowned string make_display_name (); - public void set_font_options (Cairo.FontOptions options); - public void set_resolution (double dpi); - public static int width (); - public static int width_mm (); - public void* font_options { get; set; } - public double resolution { get; set; } - public virtual signal void composited_changed (); - public virtual signal void monitors_changed (); - public virtual signal void size_changed (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Visual : GLib.Object { - [CCode (has_construct_function = false)] - protected Visual (); - public static unowned Gdk.Visual get_best (); - public static int get_best_depth (); - public static Gdk.VisualType get_best_type (); - public static unowned Gdk.Visual get_best_with_both (int depth, Gdk.VisualType visual_type); - public static unowned Gdk.Visual get_best_with_depth (int depth); - public static unowned Gdk.Visual get_best_with_type (Gdk.VisualType visual_type); - public int get_bits_per_rgb (); - public void get_blue_pixel_details (uint32 mask, int shift, int precision); - public Gdk.ByteOrder get_byte_order (); - public int get_colormap_size (); - public int get_depth (); - public void get_green_pixel_details (uint32 mask, int shift, int precision); - public void get_red_pixel_details (uint32 mask, int shift, int precision); - public unowned Gdk.Screen get_screen (); - public static unowned Gdk.Visual get_system (); - public Gdk.VisualType get_visual_type (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public class Window : GLib.Object { - [CCode (has_construct_function = false)] - public Window (Gdk.Window? parent, Gdk.WindowAttr attributes, int attributes_mask); - public void add_filter (Gdk.FilterFunc function); - public static unowned Gdk.Window at_pointer (out int win_x, out int win_y); - public void beep (); - public void begin_move_drag (int button, int root_x, int root_y, uint32 timestamp); - public void begin_paint_rect (Gdk.Rectangle rectangle); - public void begin_paint_region (Cairo.Region region); - public void begin_resize_drag (Gdk.WindowEdge edge, int button, int root_x, int root_y, uint32 timestamp); - public void configure_finished (); - public static void constrain_size (Gdk.Geometry geometry, uint flags, int width, int height, out int new_width, out int new_height); - public void coords_from_parent (double parent_x, double parent_y, double x, double y); - public void coords_to_parent (double x, double y, double parent_x, double parent_y); - public unowned Cairo.Surface create_similar_surface (Cairo.Content content, int width, int height); - public void deiconify (); - [DestroysInstance] - public void destroy (); - public void enable_synchronized_configure (); - public void end_paint (); - public bool ensure_native (); - public void flush (); - public void focus (uint32 timestamp); - public void freeze_toplevel_updates_libgtk_only (); - public void freeze_updates (); - public void fullscreen (); - public void geometry_changed (); - public bool get_accept_focus (); - public unowned Cairo.Pattern get_background_pattern (); - public GLib.List get_children (); - public unowned Cairo.Region get_clip_region (); - public bool get_composited (); - public unowned Gdk.Cursor? get_cursor (); - public bool get_decorations (out Gdk.WMDecoration decorations); - public unowned Gdk.Cursor get_device_cursor (Gdk.Device device); - public Gdk.EventMask get_device_events (Gdk.Device device); - public unowned Gdk.Window get_device_position (Gdk.Device device, int x, int y, Gdk.ModifierType mask); - public unowned Gdk.Display get_display (); - public Gdk.DragProtocol get_drag_protocol (out unowned Gdk.Window target); - public unowned Gdk.Window get_effective_parent (); - public unowned Gdk.Window get_effective_toplevel (); - public Gdk.EventMask get_events (); - public bool get_focus_on_map (); - public void get_frame_extents (out Gdk.Rectangle rect); - public void get_geometry (out int x, out int y, out int width, out int height); - public unowned Gdk.Window get_group (); - public int get_height (); - public bool get_modal_hint (); - public int get_origin (out int x, out int y); - public unowned Gdk.Window get_parent (); - public unowned Gdk.Window get_pointer (out int x, out int y, out Gdk.ModifierType mask); - public void get_position (out int x, out int y); - public void get_root_coords (int x, int y, out int root_x, out int root_y); - public void get_root_origin (out int x, out int y); - public unowned Gdk.Screen get_screen (); - public Gdk.EventMask get_source_events (Gdk.InputSource source); - public Gdk.WindowState get_state (); - public bool get_support_multidevice (); - public unowned Gdk.Window get_toplevel (); - public Gdk.WindowTypeHint get_type_hint (); - public unowned Cairo.Region get_update_area (); - public void get_user_data (void* data); - public unowned Cairo.Region get_visible_region (); - public unowned Gdk.Visual get_visual (); - public int get_width (); - public Gdk.WindowType get_window_type (); - public bool has_native (); - public void hide (); - public void iconify (); - public void input_shape_combine_region (Cairo.Region shape_region, int offset_x, int offset_y); - public void invalidate_maybe_recurse (Cairo.Region region, Gdk.WindowChildFunc child_func); - public void invalidate_rect (Gdk.Rectangle? rect, bool invalidate_children); - public void invalidate_region (Cairo.Region region, bool invalidate_children); - public bool is_destroyed (); - public bool is_input_only (); - public bool is_shaped (); - public bool is_viewable (); - public bool is_visible (); - public void lower (); - public void maximize (); - public void merge_child_input_shapes (); - public void merge_child_shapes (); - public void move (int x, int y); - public void move_region (Cairo.Region region, int dx, int dy); - public void move_resize (int x, int y, int width, int height); - public unowned GLib.List peek_children (); - public static void process_all_updates (); - public void process_updates (bool update_children); - public void raise (); - public void register_dnd (); - public void remove_filter (Gdk.FilterFunc function); - public void reparent (Gdk.Window new_parent, int x, int y); - public void resize (int width, int height); - public void restack (Gdk.Window sibling, bool above); - public void scroll (int dx, int dy); - public void set_accept_focus (bool accept_focus); - public void set_background (Gdk.Color color); - public void set_background_pattern (Cairo.Pattern pattern); - public void set_background_rgba (Gdk.RGBA rgba); - public void set_child_input_shapes (); - public void set_child_shapes (); - public void set_composited (bool composited); - public void set_cursor (Gdk.Cursor? cursor); - public static void set_debug_updates (bool setting); - public void set_decorations (Gdk.WMDecoration decorations); - public void set_device_cursor (Gdk.Device device, Gdk.Cursor cursor); - public void set_device_events (Gdk.Device device, Gdk.EventMask event_mask); - public void set_events (Gdk.EventMask event_mask); - public void set_focus_on_map (bool focus_on_map); - public void set_functions (Gdk.WMFunction functions); - public void set_geometry_hints (Gdk.Geometry geometry, Gdk.WindowHints geom_mask); - public void set_group (Gdk.Window leader); - public void set_icon_list (GLib.List pixbufs); - public void set_icon_name (string name); - public void set_keep_above (bool setting); - public void set_keep_below (bool setting); - public void set_modal_hint (bool modal); - public void set_opacity (double opacity); - public void set_override_redirect (bool override_redirect); - public void set_role (string role); - public void set_skip_pager_hint (bool skips_pager); - public void set_skip_taskbar_hint (bool skips_taskbar); - public void set_source_events (Gdk.InputSource source, Gdk.EventMask event_mask); - public void set_startup_id (string startup_id); - public bool set_static_gravities (bool use_static); - public void set_support_multidevice (bool support_multidevice); - public void set_title (string title); - public void set_transient_for (Gdk.Window parent); - public void set_type_hint (Gdk.WindowTypeHint hint); - public void set_urgency_hint (bool urgent); - public void set_user_data (void* user_data); - public void shape_combine_region (Cairo.Region shape_region, int offset_x, int offset_y); - public void show (); - public void show_unraised (); - public void stick (); - public void thaw_toplevel_updates_libgtk_only (); - public void thaw_updates (); - public void unfullscreen (); - public void unmaximize (); - public void unstick (); - public void withdraw (); - public Gdk.Cursor cursor { get; set; } - public virtual signal Cairo.Surface create_surface (int width, int height); - public virtual signal void from_embedder (double embedder_x, double embedder_y, void* offscreen_x, void* offscreen_y); - public virtual signal unowned Gdk.Window pick_embedded_child (double x, double y); - public virtual signal void to_embedder (double offscreen_x, double offscreen_y, void* embedder_x, void* embedder_y); - } - [CCode (cheader_filename = "gdk/gdk.h")] - [SimpleType] - public struct Atom { - [CCode (cname = "GDK_NONE")] - public static Gdk.Atom NONE; - public static Gdk.Atom intern (string atom_name, bool only_if_exists); - public static Gdk.Atom intern_static_string (string atom_name); - public string name (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct Color { - public uint32 pixel; - public uint16 red; - public uint16 green; - public uint16 blue; - public Gdk.Color copy (); - public bool equal (Gdk.Color colorb); - public void free (); - public uint hash (); - public static bool parse (string spec, out Gdk.Color color); - public string to_string (); - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventAny { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventButton { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public uint32 time; - public double x; - public double y; - [CCode (array_length = false)] - public weak double[] axes; - public Gdk.ModifierType state; - public uint button; - public weak Gdk.Device device; - public double x_root; - public double y_root; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventConfigure { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public int x; - public int y; - public int width; - public int height; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventCrossing { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public weak Gdk.Window subwindow; - public uint32 time; - public double x; - public double y; - public double x_root; - public double y_root; - public Gdk.CrossingMode mode; - public Gdk.NotifyType detail; - public bool focus; - public Gdk.ModifierType state; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventDND { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public weak Gdk.DragContext context; - public uint32 time; - public short x_root; - public short y_root; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventExpose { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public Gdk.Rectangle area; - public weak Cairo.Region region; - public int count; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventFocus { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public int16 @in; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventGrabBroken { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public bool keyboard; - public bool implicit; - public weak Gdk.Window grab_window; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventKey { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public uint32 time; - public Gdk.ModifierType state; - public uint keyval; - public int length; - [CCode (cname = "string")] - public weak string str; - public uint16 hardware_keycode; - public uchar group; - public uint is_modifier; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventMotion { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public uint32 time; - public double x; - public double y; - [CCode (array_length = false)] - public weak double[] axes; - public Gdk.ModifierType state; - public bool is_hint; - public weak Gdk.Device device; - public double x_root; - public double y_root; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventOwnerChange { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public weak Gdk.Window owner; - public Gdk.OwnerChange reason; - public Gdk.Atom selection; - public uint32 time; - public uint32 selection_time; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventProperty { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public Gdk.Atom atom; - public uint32 time; - public Gdk.PropertyState state; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventProximity { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public uint32 time; - public weak Gdk.Device device; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventScroll { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public uint32 time; - public double x; - public double y; - public Gdk.ModifierType state; - public Gdk.ScrollDirection direction; - public weak Gdk.Device device; - public double x_root; - public double y_root; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventSelection { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public Gdk.Atom selection; - public Gdk.Atom target; - public Gdk.Atom property; - public uint32 time; - public weak Gdk.Window requestor; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventSetting { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public Gdk.SettingAction action; - public weak string name; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventVisibility { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public Gdk.VisibilityState state; - } - [CCode (cheader_filename = "gdk/gdk.h", has_type_id = false)] - public struct EventWindowState { - public Gdk.EventType type; - public weak Gdk.Window window; - public char send_event; - public Gdk.WindowState changed_mask; - public Gdk.WindowState new_window_state; - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct Geometry { - public int min_width; - public int min_height; - public int max_width; - public int max_height; - public int base_width; - public int base_height; - public int width_inc; - public int height_inc; - public double min_aspect; - public double max_aspect; - public Gdk.Gravity win_gravity; - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct KeymapKey { - public uint keycode; - public int group; - public int level; - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct Point { - public int x; - public int y; - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct RGBA { - public double red; - public double green; - public double blue; - public double alpha; - public Gdk.RGBA copy (); - public static bool equal (void* p1, void* p2); - public void free (); - public static uint hash (void* p); - public bool parse (string spec); - public unowned string to_string (); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct Rectangle { - public int x; - public int y; - public int width; - public int height; - public bool intersect (Gdk.Rectangle src2, out Gdk.Rectangle dest); - public void union (Gdk.Rectangle src2, out Gdk.Rectangle dest); - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct TimeCoord { - public uint32 time; - [CCode (array_length = false)] - public weak double[] axes; - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct WindowAttr { - public weak string title; - public int event_mask; - public int x; - public int y; - public int width; - public int height; - public Gdk.WindowWindowClass wclass; - public weak Gdk.Visual visual; - public Gdk.WindowType window_type; - public weak Gdk.Cursor cursor; - public weak string wmclass_name; - public weak string wmclass_class; - public bool override_redirect; - public Gdk.WindowTypeHint type_hint; - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct WindowRedirect { - } - [CCode (cheader_filename = "gdk/gdk.h")] - public struct XEvent { - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_AXIS_")] - public enum AxisUse { - IGNORE, - X, - Y, - PRESSURE, - XTILT, - YTILT, - WHEEL, - LAST - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_")] - public enum ByteOrder { - LSB_FIRST, - MSB_FIRST - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_CROSSING_")] - public enum CrossingMode { - NORMAL, - GRAB, - UNGRAB, - GTK_GRAB, - GTK_UNGRAB, - STATE_CHANGED - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_")] - public enum CursorType { - X_CURSOR, - ARROW, - BASED_ARROW_DOWN, - BASED_ARROW_UP, - BOAT, - BOGOSITY, - BOTTOM_LEFT_CORNER, - BOTTOM_RIGHT_CORNER, - BOTTOM_SIDE, - BOTTOM_TEE, - BOX_SPIRAL, - CENTER_PTR, - CIRCLE, - CLOCK, - COFFEE_MUG, - CROSS, - CROSS_REVERSE, - CROSSHAIR, - DIAMOND_CROSS, - DOT, - DOTBOX, - DOUBLE_ARROW, - DRAFT_LARGE, - DRAFT_SMALL, - DRAPED_BOX, - EXCHANGE, - FLEUR, - GOBBLER, - GUMBY, - HAND1, - HAND2, - HEART, - ICON, - IRON_CROSS, - LEFT_PTR, - LEFT_SIDE, - LEFT_TEE, - LEFTBUTTON, - LL_ANGLE, - LR_ANGLE, - MAN, - MIDDLEBUTTON, - MOUSE, - PENCIL, - PIRATE, - PLUS, - QUESTION_ARROW, - RIGHT_PTR, - RIGHT_SIDE, - RIGHT_TEE, - RIGHTBUTTON, - RTL_LOGO, - SAILBOAT, - SB_DOWN_ARROW, - SB_H_DOUBLE_ARROW, - SB_LEFT_ARROW, - SB_RIGHT_ARROW, - SB_UP_ARROW, - SB_V_DOUBLE_ARROW, - SHUTTLE, - SIZING, - SPIDER, - SPRAYCAN, - STAR, - TARGET, - TCROSS, - TOP_LEFT_ARROW, - TOP_LEFT_CORNER, - TOP_RIGHT_CORNER, - TOP_SIDE, - TOP_TEE, - TREK, - UL_ANGLE, - UMBRELLA, - UR_ANGLE, - WATCH, - XTERM, - LAST_CURSOR, - BLANK_CURSOR, - CURSOR_IS_PIXMAP - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_DEVICE_TYPE_")] - public enum DeviceType { - MASTER, - SLAVE, - FLOATING - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_ACTION_")] - [Flags] - public enum DragAction { - DEFAULT, - COPY, - MOVE, - LINK, - PRIVATE, - ASK - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_DRAG_PROTO_")] - public enum DragProtocol { - NONE, - MOTIF, - XDND, - ROOTWIN, - WIN32_DROPFILES, - OLE2, - LOCAL - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_")] - [Flags] - public enum EventMask { - EXPOSURE_MASK, - POINTER_MOTION_MASK, - POINTER_MOTION_HINT_MASK, - BUTTON_MOTION_MASK, - BUTTON1_MOTION_MASK, - BUTTON2_MOTION_MASK, - BUTTON3_MOTION_MASK, - BUTTON_PRESS_MASK, - BUTTON_RELEASE_MASK, - KEY_PRESS_MASK, - KEY_RELEASE_MASK, - ENTER_NOTIFY_MASK, - LEAVE_NOTIFY_MASK, - FOCUS_CHANGE_MASK, - STRUCTURE_MASK, - PROPERTY_CHANGE_MASK, - VISIBILITY_NOTIFY_MASK, - PROXIMITY_IN_MASK, - PROXIMITY_OUT_MASK, - SUBSTRUCTURE_MASK, - SCROLL_MASK, - ALL_EVENTS_MASK - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_")] - public enum EventType { - NOTHING, - DELETE, - DESTROY, - EXPOSE, - MOTION_NOTIFY, - BUTTON_PRESS, - @2BUTTON_PRESS, - @3BUTTON_PRESS, - BUTTON_RELEASE, - KEY_PRESS, - KEY_RELEASE, - ENTER_NOTIFY, - LEAVE_NOTIFY, - FOCUS_CHANGE, - CONFIGURE, - MAP, - UNMAP, - PROPERTY_NOTIFY, - SELECTION_CLEAR, - SELECTION_REQUEST, - SELECTION_NOTIFY, - PROXIMITY_IN, - PROXIMITY_OUT, - DRAG_ENTER, - DRAG_LEAVE, - DRAG_MOTION, - DRAG_STATUS, - DROP_START, - DROP_FINISHED, - CLIENT_EVENT, - VISIBILITY_NOTIFY, - SCROLL, - WINDOW_STATE, - SETTING, - OWNER_CHANGE, - GRAB_BROKEN, - DAMAGE, - EVENT_LAST - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_EXTENSION_EVENTS_")] - public enum ExtensionMode { - NONE, - ALL, - CURSOR - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_FILTER_")] - public enum FilterReturn { - CONTINUE, - TRANSLATE, - REMOVE - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_OWNERSHIP_")] - public enum GrabOwnership { - NONE, - WINDOW, - APPLICATION - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_GRAB_")] - public enum GrabStatus { - SUCCESS, - ALREADY_GRABBED, - INVALID_TIME, - NOT_VIEWABLE, - FROZEN - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_GRAVITY_")] - public enum Gravity { - NORTH_WEST, - NORTH, - NORTH_EAST, - WEST, - CENTER, - EAST, - SOUTH_WEST, - SOUTH, - SOUTH_EAST, - STATIC - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_MODE_")] - public enum InputMode { - DISABLED, - SCREEN, - WINDOW - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_SOURCE_")] - public enum InputSource { - MOUSE, - PEN, - ERASER, - CURSOR, - KEYBOARD - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_")] - [Flags] - public enum ModifierType { - SHIFT_MASK, - LOCK_MASK, - CONTROL_MASK, - MOD1_MASK, - MOD2_MASK, - MOD3_MASK, - MOD4_MASK, - MOD5_MASK, - BUTTON1_MASK, - BUTTON2_MASK, - BUTTON3_MASK, - BUTTON4_MASK, - BUTTON5_MASK, - SUPER_MASK, - HYPER_MASK, - META_MASK, - RELEASE_MASK, - MODIFIER_MASK - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_NOTIFY_")] - public enum NotifyType { - ANCESTOR, - VIRTUAL, - INFERIOR, - NONLINEAR, - NONLINEAR_VIRTUAL, - UNKNOWN - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_OWNER_CHANGE_")] - public enum OwnerChange { - NEW_OWNER, - DESTROY, - CLOSE - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_PROP_MODE_")] - public enum PropMode { - REPLACE, - PREPEND, - APPEND - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_PROPERTY_")] - public enum PropertyState { - NEW_VALUE, - DELETE - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_SCROLL_")] - public enum ScrollDirection { - UP, - DOWN, - LEFT, - RIGHT - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_SETTING_ACTION_")] - public enum SettingAction { - NEW, - CHANGED, - DELETED - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_")] - public enum Status { - OK, - ERROR, - ERROR_PARAM, - ERROR_FILE, - ERROR_MEM - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_VISIBILITY_")] - public enum VisibilityState { - UNOBSCURED, - PARTIAL, - FULLY_OBSCURED - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_VISUAL_")] - public enum VisualType { - STATIC_GRAY, - GRAYSCALE, - STATIC_COLOR, - PSEUDO_COLOR, - TRUE_COLOR, - DIRECT_COLOR - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_DECOR_")] - [Flags] - public enum WMDecoration { - ALL, - BORDER, - RESIZEH, - TITLE, - MENU, - MINIMIZE, - MAXIMIZE - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_FUNC_")] - [Flags] - public enum WMFunction { - ALL, - RESIZE, - MOVE, - MINIMIZE, - MAXIMIZE, - CLOSE - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_WA_")] - [Flags] - public enum WindowAttributesType { - TITLE, - X, - Y, - CURSOR, - VISUAL, - WMCLASS, - NOREDIR, - TYPE_HINT - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_WINDOW_EDGE_")] - public enum WindowEdge { - NORTH_WEST, - NORTH, - NORTH_EAST, - WEST, - EAST, - SOUTH_WEST, - SOUTH, - SOUTH_EAST - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_HINT_")] - [Flags] - public enum WindowHints { - POS, - MIN_SIZE, - MAX_SIZE, - BASE_SIZE, - ASPECT, - RESIZE_INC, - WIN_GRAVITY, - USER_POS, - USER_SIZE - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_WINDOW_STATE_")] - [Flags] - public enum WindowState { - WITHDRAWN, - ICONIFIED, - MAXIMIZED, - STICKY, - FULLSCREEN, - ABOVE, - BELOW - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_WINDOW_")] - public enum WindowType { - ROOT, - TOPLEVEL, - CHILD, - TEMP, - FOREIGN, - OFFSCREEN - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_WINDOW_TYPE_HINT_")] - public enum WindowTypeHint { - NORMAL, - DIALOG, - MENU, - TOOLBAR, - SPLASHSCREEN, - UTILITY, - DOCK, - DESKTOP, - DROPDOWN_MENU, - POPUP_MENU, - TOOLTIP, - NOTIFICATION, - COMBO, - DND - } - [CCode (cheader_filename = "gdk/gdk.h", cprefix = "GDK_INPUT_")] - public enum WindowWindowClass { - OUTPUT, - ONLY - } - [CCode (cheader_filename = "gdk/gdk.h")] - public delegate void EventFunc (Gdk.Event event); - [CCode (cheader_filename = "gdk/gdk.h")] - public delegate Gdk.FilterReturn FilterFunc (Gdk.XEvent xevent, Gdk.Event event); - [CCode (cheader_filename = "gdk/gdk.h")] - public delegate bool WindowChildFunc (Gdk.Window window); - [CCode (cheader_filename = "gdk/gdk.h")] - public const int CURRENT_TIME; - [CCode (cheader_filename = "gdk/gdk.h")] - public const int MAX_TIMECOORD_AXES; - [CCode (cheader_filename = "gdk/gdk.h")] - public const int PARENT_RELATIVE; - [CCode (cheader_filename = "gdk/gdk.h")] - public const int PRIORITY_REDRAW; - [CCode (cheader_filename = "gdk/gdk.h")] - public const Gdk.Atom SELECTION_CLIPBOARD; - [CCode (cheader_filename = "gdk/gdk.h")] - public const Gdk.Atom SELECTION_PRIMARY; - [CCode (cheader_filename = "gdk/gdk.h")] - public const Gdk.Atom SELECTION_SECONDARY; - [CCode (cheader_filename = "gdk/gdk.h")] - public static void add_option_entries_libgtk_only (GLib.OptionGroup group); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void beep (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static Cairo.Context cairo_create (Gdk.Window window); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool cairo_get_clip_rectangle (Cairo.Context cr, Gdk.Rectangle rect); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void cairo_rectangle (Cairo.Context cr, Gdk.Rectangle rectangle); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void cairo_region (Cairo.Context cr, Cairo.Region region); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Cairo.Region cairo_region_create_from_surface (Cairo.Surface surface); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void cairo_set_source_color (Cairo.Context cr, Gdk.Color color); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void cairo_set_source_pixbuf (Cairo.Context cr, Gdk.Pixbuf pixbuf, double pixbuf_x, double pixbuf_y); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void cairo_set_source_rgba (Cairo.Context cr, Gdk.RGBA rgba); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void cairo_set_source_window (Cairo.Context cr, Gdk.Window window, double x, double y); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void disable_multidevice (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void drag_abort (Gdk.DragContext context, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.DragContext drag_begin (Gdk.Window window, GLib.List targets); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.DragContext drag_begin_for_device (Gdk.Window window, Gdk.Device device, GLib.List targets); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void drag_drop (Gdk.DragContext context, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool drag_drop_succeeded (Gdk.DragContext context); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void drag_find_window_for_screen (Gdk.DragContext context, Gdk.Window drag_window, Gdk.Screen screen, int x_root, int y_root, out unowned Gdk.Window dest_window, Gdk.DragProtocol protocol); - [CCode (cheader_filename = "gdk/gdk.h")] - public static Gdk.Atom drag_get_selection (Gdk.DragContext context); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool drag_motion (Gdk.DragContext context, Gdk.Window dest_window, Gdk.DragProtocol protocol, int x_root, int y_root, Gdk.DragAction suggested_action, Gdk.DragAction possible_actions, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void drag_status (Gdk.DragContext context, Gdk.DragAction action, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void drop_finish (Gdk.DragContext context, bool success, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void drop_reply (Gdk.DragContext context, bool accepted, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static int error_trap_pop (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void error_trap_pop_ignored (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void error_trap_push (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool events_get_angle (Gdk.Event event1, Gdk.Event event2, double angle); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool events_get_center (Gdk.Event event1, Gdk.Event event2, double x, double y); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool events_get_distance (Gdk.Event event1, Gdk.Event event2, double distance); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool events_pending (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void flush (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.Window get_default_root_window (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned string get_display (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned string get_display_arg_name (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned string get_program_class (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool get_show_events (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void init ([CCode (array_length_pos = 0.9)] ref unowned string[] argv); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool init_check ([CCode (array_length_pos = 0.9)] ref unowned string[] argv); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void keyval_convert_case (uint symbol, uint lower, uint upper); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint keyval_from_name (string keyval_name); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool keyval_is_lower (uint keyval); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool keyval_is_upper (uint keyval); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned string keyval_name (uint keyval); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint keyval_to_lower (uint keyval); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint32 keyval_to_unicode (uint keyval); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint keyval_to_upper (uint keyval); - [CCode (cheader_filename = "gdk/gdk.h")] - public static GLib.List list_visuals (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void notify_startup_complete (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void notify_startup_complete_with_id (string startup_id); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.Window? offscreen_window_get_embedder (Gdk.Window window); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Cairo.Surface offscreen_window_get_surface (Gdk.Window window); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void offscreen_window_set_embedder (Gdk.Window window, Gdk.Window embedder); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Pango.Context pango_context_get (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Pango.Context pango_context_get_for_screen (Gdk.Screen screen); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Cairo.Region pango_layout_get_clip_region (Pango.Layout layout, int x_origin, int y_origin, int index_ranges, int n_ranges); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Cairo.Region pango_layout_line_get_clip_region (Pango.LayoutLine line, int x_origin, int y_origin, int index_ranges, int n_ranges); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void parse_args (int argc, string argv); - [CCode (cheader_filename = "gdk/gdk.h")] - public static Gdk.Pixbuf pixbuf_get_from_surface (Cairo.Surface surface, int src_x, int src_y, int width, int height); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned Gdk.Pixbuf pixbuf_get_from_window (Gdk.Window window, int src_x, int src_y, int width, int height); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void pre_parse_libgtk_only (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void property_change (Gdk.Window window, Gdk.Atom property, Gdk.Atom type, int format, Gdk.PropMode mode, [CCode (array_length = false)] uchar[] data, int nelements); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void property_delete (Gdk.Window window, Gdk.Atom property); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool property_get (Gdk.Window window, Gdk.Atom property, Gdk.Atom type, ulong offset, ulong length, int pdelete, out Gdk.Atom actual_property_type, out int actual_format, [CCode (array_length_pos = 8.9)] out uchar[] data); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void query_depths (int depths, int count); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void query_visual_types (out Gdk.VisualType visual_types, int count); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.convert", since = "vala-0.12")] - public static void selection_convert (Gdk.Window requestor, Gdk.Atom selection, Gdk.Atom target, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.owner_get", since = "vala-0.12")] - public static unowned Gdk.Window selection_owner_get (Gdk.Atom selection); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.owner_get_for_display", since = "vala-0.12")] - public static unowned Gdk.Window selection_owner_get_for_display (Gdk.Display display, Gdk.Atom selection); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.owner_set", since = "vala-0.12")] - public static bool selection_owner_set (Gdk.Window owner, Gdk.Atom selection, uint32 time_, bool send_event); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.owner_set_for_display", since = "vala-0.12")] - public static bool selection_owner_set_for_display (Gdk.Display display, Gdk.Window owner, Gdk.Atom selection, uint32 time_, bool send_event); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.property_get", since = "vala-0.12")] - public static int selection_property_get (Gdk.Window requestor, uchar[] data, out Gdk.Atom prop_type, int prop_format); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.send_notify", since = "vala-0.12")] - public static void selection_send_notify (Gdk.Window requestor, Gdk.Atom selection, Gdk.Atom target, Gdk.Atom property, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - [Deprecated (replacement = "Selection.send_notify_for_display", since = "vala-0.12")] - public static void selection_send_notify_for_display (Gdk.Display display, Gdk.Window requestor, Gdk.Atom selection, Gdk.Atom target, Gdk.Atom property, uint32 time_); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void set_double_click_time (uint msec); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void set_program_class (string program_class); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void set_show_events (bool show_events); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool setting_get (string name, GLib.Value value); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void test_render_sync (Gdk.Window window); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool test_simulate_button (Gdk.Window window, int x, int y, uint button, Gdk.ModifierType modifiers, Gdk.EventType button_pressrelease); - [CCode (cheader_filename = "gdk/gdk.h")] - public static bool test_simulate_key (Gdk.Window window, int x, int y, uint keyval, Gdk.ModifierType modifiers, Gdk.EventType key_pressrelease); - [CCode (cheader_filename = "gdk/gdk.h")] - public static int text_property_to_utf8_list_for_display (Gdk.Display display, Gdk.Atom encoding, int format, uchar[] text, int length, string list); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint threads_add_idle (GLib.SourceFunc function); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint threads_add_idle_full (int priority, owned GLib.SourceFunc function); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint threads_add_timeout (uint interval, GLib.SourceFunc function); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint threads_add_timeout_full (int priority, uint interval, owned GLib.SourceFunc function); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint threads_add_timeout_seconds (uint interval, GLib.SourceFunc function); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint threads_add_timeout_seconds_full (int priority, uint interval, owned GLib.SourceFunc function); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void threads_enter (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void threads_init (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void threads_leave (); - [CCode (cheader_filename = "gdk/gdk.h")] - public static void threads_set_lock_functions (GLib.Callback enter_fn, GLib.Callback leave_fn); - [CCode (cheader_filename = "gdk/gdk.h")] - public static uint unicode_to_keyval (uint32 wc); - [CCode (cheader_filename = "gdk/gdk.h")] - public static unowned string utf8_to_string_target (string str); -} diff -Nru shotwell-0.11.91/vapi/gphoto.h shotwell-0.11.92/vapi/gphoto.h --- shotwell-0.11.91/vapi/gphoto.h 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/gphoto.h 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/vapi/hmac-glib.vapi shotwell-0.11.92/vapi/hmac-glib.vapi --- shotwell-0.11.91/vapi/hmac-glib.vapi 1970-01-01 00:00:00.000000000 +0000 +++ shotwell-0.11.92/vapi/hmac-glib.vapi 2012-02-20 20:47:27.000000000 +0000 @@ -0,0 +1,11 @@ +/* Copyright 2010-2012 Yorba Foundation + * + * This software is licensed under the GNU LGPL (version 2.1 or later). + * See the COPYING file in this distribution. + */ +namespace GLib { + [CCode (cheader_filename="glib.h", cname="g_compute_hmac_for_string")] + string compute_hmac_for_string(ChecksumType hash_kind, string key, size_t key_length, + string data, size_t data_length); +} + diff -Nru shotwell-0.11.91/vapi/LConv.vapi shotwell-0.11.92/vapi/LConv.vapi --- shotwell-0.11.91/vapi/LConv.vapi 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/LConv.vapi 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/vapi/libexif.vapi shotwell-0.11.92/vapi/libexif.vapi --- shotwell-0.11.91/vapi/libexif.vapi 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/libexif.vapi 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. diff -Nru shotwell-0.11.91/vapi/libgphoto2.vapi shotwell-0.11.92/vapi/libgphoto2.vapi --- shotwell-0.11.91/vapi/libgphoto2.vapi 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/libgphoto2.vapi 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2009-2011 Yorba Foundation +/* Copyright 2009-2012 Yorba Foundation * * This software is licensed under the GNU LGPL (version 2.1 or later). * See the COPYING file in this distribution. @@ -104,7 +104,7 @@ public class CameraFile { [CCode (cname="gp_file_new")] public static Result create(out CameraFile file); - public Result get_data_and_size(out unowned uint8[] data); + public Result get_data_and_size(out uint8 *data, out ulong data_len); public Result save(string filename); public Result slurp(uint8[] data, out size_t readlen); } diff -Nru shotwell-0.11.91/vapi/libraw.vapi shotwell-0.11.92/vapi/libraw.vapi --- shotwell-0.11.91/vapi/libraw.vapi 2012-01-06 01:26:06.000000000 +0000 +++ shotwell-0.11.92/vapi/libraw.vapi 2012-02-20 20:47:27.000000000 +0000 @@ -1,4 +1,4 @@ -/* Copyright 2010-2011 Yorba Foundation +/* Copyright 2010-2012 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution.