[gnome-photos/wip/rishi/edit-undo: 2/2] application, done-notification: Use a GAction to handle the revert



commit 5fa3af66565db5fe2ed03f55704049118c9a0f9f
Author: Debarshi Ray <debarshir gnome org>
Date:   Sun Jul 10 01:32:34 2016 +0200

    application, done-notification: Use a GAction to handle the revert
    
    This makes it easier to properly manage the lifecycle of the objects.
    In future we can add nice things like keyboard shortcuts.
    
    Earlier, we were taking a reference on the DoneNotification to keep it
    alive across the asynchronous calls. However, taking references on
    GtkWidgets outside a GtkContainer is tricky. gtk_widget_destroy will
    leave them in a disposed-but-not-finalized state (unless we drop our
    own reference on GtkWidget::destroy, which defeats the purpose of
    taking the reference in the first place). This means that the guts of
    the DoneNotification instance could get destroyed, even while we held
    a reference, if someone closed the window while it was reverting and
    saving the pipeline.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763908

 src/photos-application.c       |   69 ++++++++++++++++++++++++++++++++++++
 src/photos-done-notification.c |   75 ++++++++--------------------------------
 2 files changed, 84 insertions(+), 60 deletions(-)
---
diff --git a/src/photos-application.c b/src/photos-application.c
index c438f95..d0e44d2 100644
--- a/src/photos-application.c
+++ b/src/photos-application.c
@@ -80,6 +80,7 @@ struct _PhotosApplication
   GSimpleAction *edit_action;
   GSimpleAction *edit_cancel_action;
   GSimpleAction *edit_done_action;
+  GSimpleAction *edit_revert_action;
   GSimpleAction *fs_action;
   GSimpleAction *gear_action;
   GSimpleAction *insta_action;
@@ -788,6 +789,65 @@ photos_application_edit_current (PhotosApplication *self)
 
 
 static void
+photos_application_edit_revert_pipeline_save (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  PhotosApplication *self = PHOTOS_APPLICATION (user_data);
+  GError *error;
+  PhotosBaseItem *item = PHOTOS_BASE_ITEM (source_object);
+
+  error = NULL;
+  if (!photos_base_item_pipeline_save_finish (item, res, &error))
+    {
+      g_warning ("Unable to save pipeline: %s", error->message);
+      g_error_free (error);
+    }
+
+  photos_application_release (self);
+}
+
+
+static void
+photos_application_edit_revert_revert (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  PhotosApplication *self = PHOTOS_APPLICATION (user_data);
+  GError *error;
+  PhotosBaseItem *item = PHOTOS_BASE_ITEM (source_object);
+
+  error = NULL;
+  if (!photos_base_item_operations_revert_finish (item, res, &error))
+    {
+      g_warning ("Unable to process item: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  photos_application_hold (self);
+  photos_base_item_pipeline_save_async (item, NULL, photos_application_edit_revert_pipeline_save, self);
+
+ out:
+  g_action_activate (G_ACTION (self->draw_action), NULL);
+  photos_application_release (self);
+}
+
+
+static void
+photos_application_edit_revert (PhotosApplication *self, GVariant *parameter)
+{
+  PhotosBaseItem *item;
+  const gchar *id;
+
+  id = g_variant_get_string (parameter, NULL);
+  g_return_if_fail (id != NULL && id[0] != '\0');
+
+  item = PHOTOS_BASE_ITEM (photos_base_manager_get_object_by_id (self->state->item_mngr, id));
+  g_return_if_fail (item != NULL);
+
+  photos_application_hold (self);
+  photos_base_item_operations_revert_async (item, NULL, photos_application_edit_revert_revert, self);
+}
+
+
+static void
 photos_application_fullscreen (PhotosApplication *self, GVariant *parameter)
 {
   photos_mode_controller_toggle_fullscreen (self->state->mode_cntrlr);
@@ -1530,6 +1590,14 @@ photos_application_startup (GApplication *application)
   self->edit_done_action = g_simple_action_new ("edit-done", NULL);
   g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->edit_done_action));
 
+  self->edit_revert_action = g_simple_action_new ("edit-revert", G_VARIANT_TYPE_STRING);
+  g_simple_action_set_enabled (self->edit_revert_action, FALSE);
+  g_signal_connect_swapped (self->edit_revert_action,
+                            "activate",
+                            G_CALLBACK (photos_application_edit_revert),
+                            self);
+  g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->edit_revert_action));
+
   self->fs_action = g_simple_action_new ("fullscreen", NULL);
   g_signal_connect_swapped (self->fs_action, "activate", G_CALLBACK (photos_application_fullscreen), self);
   g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (self->fs_action));
@@ -1689,6 +1757,7 @@ photos_application_dispose (GObject *object)
   g_clear_object (&self->edit_action);
   g_clear_object (&self->edit_cancel_action);
   g_clear_object (&self->edit_done_action);
+  g_clear_object (&self->edit_revert_action);
   g_clear_object (&self->fs_action);
   g_clear_object (&self->gear_action);
   g_clear_object (&self->insta_action);
diff --git a/src/photos-done-notification.c b/src/photos-done-notification.c
index 901a233..c3425bd 100644
--- a/src/photos-done-notification.c
+++ b/src/photos-done-notification.c
@@ -26,6 +26,7 @@
 
 #include "photos-base-item.h"
 #include "photos-done-notification.h"
+#include "photos-filterable.h"
 #include "photos-icons.h"
 #include "photos-notification-manager.h"
 #include "photos-search-context.h"
@@ -34,6 +35,7 @@
 struct _PhotosDoneNotification
 {
   GtkGrid parent_instance;
+  GAction *edit_revert_action;
   PhotosBaseItem *item;
   GtkWidget *ntfctn_mngr;
   guint timeout_id;
@@ -69,6 +71,7 @@ photos_done_notification_remove_timeout (PhotosDoneNotification *self)
 static void
 photos_done_notification_destroy (PhotosDoneNotification *self)
 {
+  g_simple_action_set_enabled (G_SIMPLE_ACTION (self->edit_revert_action), FALSE);
   photos_done_notification_remove_timeout (self);
   gtk_widget_destroy (GTK_WIDGET (self));
 }
@@ -86,69 +89,14 @@ photos_done_notification_timeout (gpointer user_data)
 
 
 static void
-photos_done_notification_pipeline_save_finish (GObject *source_object, GAsyncResult *res, gpointer user_data)
-{
-  PhotosDoneNotification *self = PHOTOS_DONE_NOTIFICATION (user_data);
-  GApplication *app;
-  GError *error = NULL;
-  PhotosBaseItem *item = PHOTOS_BASE_ITEM (source_object);
-
-  if (!photos_base_item_pipeline_save_finish (item, res, &error))
-    {
-      g_warning ("Unable to save pipeline: %s", error->message);
-      g_error_free (error);
-    }
-
-  app = g_application_get_default ();
-  g_application_release (app);
-  g_object_unref (self);
-}
-
-
-static void
-photos_done_notification_edit_undo_process (GObject *source_object, GAsyncResult *res, gpointer user_data)
-{
-  PhotosDoneNotification *self = PHOTOS_DONE_NOTIFICATION (user_data);
-  GApplication *app;
-  GAction *action;
-  GError *error = NULL;
-  PhotosBaseItem *item = PHOTOS_BASE_ITEM (source_object);
-
-  app = g_application_get_default ();
-
-  if (!photos_base_item_operations_revert_finish (item, res, &error))
-    {
-      g_warning ("Unable to process item: %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  g_application_hold (app);
-  photos_base_item_pipeline_save_async (item,
-                                        NULL,
-                                        photos_done_notification_pipeline_save_finish,
-                                        g_object_ref (self));
-
- out:
-  action = g_action_map_lookup_action (G_ACTION_MAP (app), "draw-current");
-  g_action_activate (action, NULL);
-  g_application_release (app);
-  g_object_unref (self);
-}
-
-
-static void
 photos_done_notification_undo_clicked (PhotosDoneNotification *self)
 {
-  GApplication *app;
-
-  app = g_application_get_default ();
-  g_application_hold (app);
+  GVariant *parameter;
+  const gchar *id;
 
-  photos_base_item_operations_revert_async (self->item,
-                                            NULL,
-                                            photos_done_notification_edit_undo_process,
-                                            g_object_ref (self));
+  id = photos_filterable_get_id (PHOTOS_FILTERABLE (self->item));
+  parameter = g_variant_new_string (id);
+  g_action_activate (self->edit_revert_action, parameter);
 
   photos_done_notification_destroy (self);
 }
@@ -199,6 +147,7 @@ photos_done_notification_constructed (GObject *object)
 
   photos_notification_manager_add_notification (PHOTOS_NOTIFICATION_MANAGER (self->ntfctn_mngr),
                                                 GTK_WIDGET (self));
+  g_simple_action_set_enabled (G_SIMPLE_ACTION (self->edit_revert_action), TRUE);
 
   self->timeout_id = g_timeout_add_seconds (DONE_TIMEOUT, photos_done_notification_timeout, self);
 }
@@ -209,6 +158,7 @@ photos_done_notification_dispose (GObject *object)
 {
   PhotosDoneNotification *self = PHOTOS_DONE_NOTIFICATION (object);
 
+  g_simple_action_set_enabled (G_SIMPLE_ACTION (self->edit_revert_action), FALSE);
   photos_done_notification_remove_timeout (self);
 
   g_clear_object (&self->item);
@@ -242,6 +192,11 @@ photos_done_notification_set_property (GObject *object, guint prop_id, const GVa
 static void
 photos_done_notification_init (PhotosDoneNotification *self)
 {
+  GApplication *app;
+
+  app = g_application_get_default ();
+  self->edit_revert_action = g_action_map_lookup_action (G_ACTION_MAP (app), "edit-revert");
+
   self->ntfctn_mngr = photos_notification_manager_dup_singleton ();
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]