From 5e9f4eea451a77ba3b93db3747841ed2bd969e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 30 Sep 2018 14:09:20 +0200 Subject: New upstream version 0.30.1 --- src/Commands.vala | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 217 insertions(+), 1 deletion(-) (limited to 'src/Commands.vala') diff --git a/src/Commands.vala b/src/Commands.vala index 7441a50..6924f82 100644 --- a/src/Commands.vala +++ b/src/Commands.vala @@ -920,7 +920,6 @@ public abstract class MovePhotosCommand : Command { } public override void execute() { - // create the new event base.execute(); @@ -2507,3 +2506,220 @@ public class FlagUnflagCommand : MultipleDataSourceAtOnceCommand { } } } + +#if ENABLE_FACES +public class RemoveFacesFromPhotosCommand : SimpleProxyableCommand { + private Gee.Map map_source_geometry = new Gee.HashMap(); + + public RemoveFacesFromPhotosCommand(Face face, Gee.Collection sources) { + base (face, + Resources.remove_face_from_photos_label(face.get_name(), sources.size), + face.get_name()); + + foreach (MediaSource source in sources) { + FaceLocation? face_location = + FaceLocation.get_face_location(face.get_face_id(), ((Photo) source).get_photo_id()); + assert(face_location != null); + + this.map_source_geometry.set(source, face_location.get_serialized_geometry()); + } + + LibraryPhoto.global.item_destroyed.connect(on_source_destroyed); + Video.global.item_destroyed.connect(on_source_destroyed); + } + + ~RemoveFacesFromPhotosCommand() { + LibraryPhoto.global.item_destroyed.disconnect(on_source_destroyed); + Video.global.item_destroyed.disconnect(on_source_destroyed); + } + + public override void execute_on_source(DataSource source) { + ((Face) source).detach_many(map_source_geometry.keys); + } + + public override void undo_on_source(DataSource source) { + Face face = (Face) source; + + face.attach_many(map_source_geometry.keys); + foreach (Gee.Map.Entry entry in map_source_geometry.entries) + FaceLocation.create(face.get_face_id(), ((Photo) entry.key).get_photo_id(), entry.value); + } + + private void on_source_destroyed(DataSource source) { + if (map_source_geometry.keys.contains((MediaSource) source)) + get_command_manager().reset(); + } +} + +public class RenameFaceCommand : SimpleProxyableCommand { + private string old_name; + private string new_name; + + public RenameFaceCommand(Face face, string new_name) { + base (face, Resources.rename_face_label(face.get_name(), new_name), face.get_name()); + + old_name = face.get_name(); + this.new_name = new_name; + } + + protected override void execute_on_source(DataSource source) { + if (!((Face) source).rename(new_name)) + AppWindow.error_message(Resources.rename_face_exists_message(new_name)); + } + + protected override void undo_on_source(DataSource source) { + if (!((Face) source).rename(old_name)) + AppWindow.error_message(Resources.rename_face_exists_message(old_name)); + } +} + +public class DeleteFaceCommand : SimpleProxyableCommand { + private Gee.Map photo_geometry_map = new Gee.HashMap + ((Gee.HashDataFunc)FaceLocation.photo_id_hash, (Gee.EqualDataFunc)FaceLocation.photo_ids_equal); + + public DeleteFaceCommand(Face face) { + base (face, Resources.delete_face_label(face.get_name()), face.get_name()); + + // we can't use the Gee.Map returned by FaceLocation.get_locations_by_face + // because it will be modified in execute_on_source + Gee.Map? temp = FaceLocation.get_locations_by_face(face); + assert(temp != null); + foreach (Gee.Map.Entry entry in temp.entries) + photo_geometry_map.set(entry.key, entry.value.get_serialized_geometry()); + } + + protected override void execute_on_source(DataSource source) { + FaceID face_id = ((Face) source).get_face_id(); + foreach (PhotoID photo_id in photo_geometry_map.keys) + FaceLocation.destroy(face_id, photo_id); + + Face.global.destroy_marked(Face.global.mark(source), false); + } + + protected override void undo_on_source(DataSource source) { + // merely instantiating the Face will rehydrate it ... should always work, because the + // undo stack is cleared if the proxy ever breaks + assert(source is Face); + + foreach (Gee.Map.Entry entry in photo_geometry_map.entries) { + Photo? photo = LibraryPhoto.global.fetch(entry.key); + + if (photo != null) { + Face face = (Face) source; + + face.attach(photo); + FaceLocation.create(face.get_face_id(), entry.key, entry.value); + } + } + } +} + +public class ModifyFacesCommand : SingleDataSourceCommand { + private MediaSource media; + private Gee.ArrayList to_add = new Gee.ArrayList(); + private Gee.ArrayList to_remove = new Gee.ArrayList(); + private Gee.Map to_update = new Gee.HashMap(); + private Gee.Map geometries = new Gee.HashMap(); + + public ModifyFacesCommand(MediaSource media, Gee.Map new_face_list) { + base (media, Resources.MODIFY_FACES_LABEL, ""); + + this.media = media; + + // Remove any face that's in the original list but not the new one + Gee.Collection? original_faces = Face.global.fetch_for_source(media); + if (original_faces != null) { + foreach (Face face in original_faces) { + if (!new_face_list.keys.contains(face)) { + SourceProxy proxy = face.get_proxy(); + + to_remove.add(proxy); + proxy.broken.connect(on_proxy_broken); + + FaceLocation? face_location = + FaceLocation.get_face_location(face.get_face_id(), ((Photo) media).get_photo_id()); + assert(face_location != null); + + geometries.set(proxy, face_location.get_serialized_geometry()); + } + } + } + + // Add any face that's in the new list but not the original + foreach (Gee.Map.Entry entry in new_face_list.entries) { + if (original_faces == null || !original_faces.contains(entry.key)) { + SourceProxy proxy = entry.key.get_proxy(); + + to_add.add(proxy); + proxy.broken.connect(on_proxy_broken); + + geometries.set(proxy, entry.value); + } else { + // If it is already in the original list we need to check if it's + // geometry has changed. + FaceLocation? face_location = + FaceLocation.get_face_location(entry.key.get_face_id(), ((Photo) media).get_photo_id()); + assert(face_location != null); + + string old_geometry = face_location.get_serialized_geometry(); + if (old_geometry != entry.value) { + SourceProxy proxy = entry.key.get_proxy(); + + to_update.set(proxy, entry.value); + proxy.broken.connect(on_proxy_broken); + + geometries.set(proxy, old_geometry); + } + } + } + } + + ~ModifyFacesCommand() { + foreach (SourceProxy proxy in to_add) + proxy.broken.disconnect(on_proxy_broken); + + foreach (SourceProxy proxy in to_remove) + proxy.broken.disconnect(on_proxy_broken); + + foreach (SourceProxy proxy in to_update.keys) + proxy.broken.disconnect(on_proxy_broken); + } + + public override void execute() { + foreach (SourceProxy proxy in to_add) { + Face face = (Face) proxy.get_source(); + face.attach(media); + FaceLocation.create(face.get_face_id(), ((Photo) media).get_photo_id(), geometries.get(proxy)); + } + + foreach (SourceProxy proxy in to_remove) + ((Face) proxy.get_source()).detach(media); + + foreach (Gee.Map.Entry entry in to_update.entries) { + Face face = (Face) entry.key.get_source(); + FaceLocation.create(face.get_face_id(), ((Photo) media).get_photo_id(), entry.value); + } + } + + public override void undo() { + foreach (SourceProxy proxy in to_add) + ((Face) proxy.get_source()).detach(media); + + foreach (SourceProxy proxy in to_remove) { + Face face = (Face) proxy.get_source(); + face.attach(media); + FaceLocation.create(face.get_face_id(), ((Photo) media).get_photo_id(), geometries.get(proxy)); + } + + foreach (SourceProxy proxy in to_update.keys) { + Face face = (Face) proxy.get_source(); + FaceLocation.create(face.get_face_id(), ((Photo) media).get_photo_id(), geometries.get(proxy)); + } + } + + private void on_proxy_broken() { + get_command_manager().reset(); + } +} + +#endif -- cgit v1.2.3