[gnome-utils] screenshot: use GIO to asynchronously save the screenshot pixbuf



commit 5d83a8954885238bd8b191455e29d6ef98b0f8de
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Mon Sep 26 15:45:23 2011 -0400

    screenshot: use GIO to asynchronously save the screenshot pixbuf
    
    Right now we have a somewhat byzantine process for saving files:
    - we trigger a child process that saves the screenshot in /tmp as soon
      as the pixbuf is available
    - we call into NautilusFileOperations to copy that tmp pixbuf into the
      user-specified file
    
    The only reason why this would be needed nowadays is to support DnD from
    the dialog to e.g. the desktop, or a folder. Remove support for that
    (we're going towards a completely headless gnome-screenshot anyway) and
    refactor the rest of the code to use simple async GIO methods instead.

 gnome-screenshot/Makefile.am         |    2 -
 gnome-screenshot/gnome-screenshot.c  |  253 +++++++++++++++---------------
 gnome-screenshot/screenshot-dialog.c |   51 +-----
 gnome-screenshot/screenshot-dialog.h |    2 -
 gnome-screenshot/screenshot-save.c   |  287 ----------------------------------
 gnome-screenshot/screenshot-save.h   |   33 ----
 6 files changed, 132 insertions(+), 496 deletions(-)
---
diff --git a/gnome-screenshot/Makefile.am b/gnome-screenshot/Makefile.am
index 827a1b1..4f0d498 100644
--- a/gnome-screenshot/Makefile.am
+++ b/gnome-screenshot/Makefile.am
@@ -27,8 +27,6 @@ gnome_screenshot_SOURCES = \
 	screenshot-shadow.h		\
 	screenshot-utils.c		\
 	screenshot-utils.h		\
-	screenshot-save.c		\
-	screenshot-save.h		\
 	$(NULL)
 
 gnome_screenshot_CFLAGS =		\
diff --git a/gnome-screenshot/gnome-screenshot.c b/gnome-screenshot/gnome-screenshot.c
index 2793bc7..ed3a3e0 100644
--- a/gnome-screenshot/gnome-screenshot.c
+++ b/gnome-screenshot/gnome-screenshot.c
@@ -46,7 +46,6 @@
 #include "screenshot-interactive-dialog.h"
 #include "screenshot-shadow.h"
 #include "screenshot-utils.h"
-#include "screenshot-save.h"
 #include "screenshot-dialog.h"
 #include "cheese-flash.h"
 
@@ -57,13 +56,9 @@
 static GdkPixbuf *screenshot = NULL;
 
 /* Global variables*/
-static char *temporary_file = NULL;
-static gboolean save_immediately = FALSE;
 static CheeseFlash *flash = NULL;
 static GDBusConnection *connection = NULL;
-
-/* some local prototypes */
-static void  save_done_notification (gpointer   data);
+static gchar *icc_profile_base64 = NULL;
 
 static void
 save_folder_to_settings (ScreenshotDialog *dialog)
@@ -121,119 +116,146 @@ error_dialog_response_cb (GtkDialog *d,
                           ScreenshotDialog *dialog)
 {
   gtk_widget_destroy (GTK_WIDGET (d));
-  
+
   screenshot_dialog_focus_entry (dialog);
 }
 
 static void
-save_callback (GObject *source,
-               GAsyncResult *res,
-               gpointer user_data)
+save_file_failed_error (ScreenshotDialog *dialog,
+                        GError *error)
 {
-  ScreenshotDialog *dialog = user_data;
   GtkWidget *toplevel;
-  GError *error = NULL;
-  
+  GtkWidget *error_dialog;
+  char *folder;
+
   toplevel = screenshot_dialog_get_toplevel (dialog);
   screenshot_dialog_set_busy (dialog, FALSE);
 
-  g_dbus_connection_call_finish (connection, res, &error);
+  /* we had an error, display a dialog to the user and let him choose
+   * another name/location to save the screenshot.
+   */      
+  folder = screenshot_dialog_get_folder (dialog);
+  error_dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
+                                         GTK_DIALOG_DESTROY_WITH_PARENT,
+                                         GTK_MESSAGE_ERROR,
+                                         GTK_BUTTONS_OK,
+                                         _("Error while saving screenshot"));
+
+  /* translators: first %s is the folder URI, second %s is the VFS error */
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
+                                            _("Impossible to save the screenshot "
+                                              "to %s.\n Error was %s.\n Please choose another "
+                                              "location and retry."), folder, error->message);
+  gtk_widget_show (error_dialog);
+  g_signal_connect (error_dialog,
+                    "response",
+                    G_CALLBACK (error_dialog_response_cb),
+                    dialog);
+
+  g_free (folder);
+}
+
+static void
+save_file_completed (ScreenshotDialog *dialog)
+{
+  GtkWidget *toplevel;
+
+  toplevel = screenshot_dialog_get_toplevel (dialog);
+
+  save_folder_to_settings (dialog);
+  set_recent_entry (dialog);
+  gtk_widget_destroy (toplevel);
+
+  /* we're done, stop the mainloop now */
+  gtk_main_quit ();
+}
+
+static void
+save_pixbuf_ready_cb (GObject *source,
+                      GAsyncResult *res,
+                      gpointer user_data)
+{
+  GError *error = NULL;
+  ScreenshotDialog *dialog = user_data;
+
+  gdk_pixbuf_save_to_stream_finish (res, &error);
 
   if (error != NULL)
     {
-      /* we had an error, display a dialog to the user and let him choose
-       * another name/location to save the screenshot.
-       */
-      GtkWidget *error_dialog;
-      char *folder;
-      
-      folder = screenshot_dialog_get_folder (dialog);
-      error_dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel),
-                                       GTK_DIALOG_DESTROY_WITH_PARENT,
-                                       GTK_MESSAGE_ERROR,
-                                       GTK_BUTTONS_OK,
-                                       _("Error while saving screenshot"));
-
-      /* translators: first %s is the folder URI, second %s is the VFS error */
-      gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
-                                                _("Impossible to save the screenshot "
-                                                  "to %s.\n Error was %s.\n Please choose another "
-                                                  "location and retry."), folder, error->message);
-      gtk_widget_show (error_dialog);
-      g_signal_connect (error_dialog,
-                        "response",
-                        G_CALLBACK (error_dialog_response_cb),
-                        dialog);
-
-      g_free (folder);
+      save_file_failed_error (dialog, error);
       g_error_free (error);
+      return;
     }
-  else
+
+  save_file_completed (dialog);
+}
+
+static void
+save_file_create_ready_cb (GObject *source,
+                           GAsyncResult *res,
+                           gpointer user_data)
+{
+  GFileOutputStream *os;
+  GError *error = NULL;
+  ScreenshotDialog *dialog = user_data;
+
+  os = g_file_create_finish (G_FILE (source), res, &error);
+
+  if (error != NULL)
     {
-      save_folder_to_settings (dialog);
-      set_recent_entry (dialog);
-      gtk_widget_destroy (toplevel);
-      
-      /* we're done, stop the mainloop now */
-      gtk_main_quit ();
+      save_file_failed_error (dialog, error);
+      g_error_free (error);
+      return;
     }
+
+  if (icc_profile_base64 != NULL)
+    gdk_pixbuf_save_to_stream_async (screenshot,
+                                     G_OUTPUT_STREAM (os),
+                                     "png", NULL,
+                                     save_pixbuf_ready_cb, dialog,
+                                     "icc-profile", icc_profile_base64,
+                                     "tEXt::Software", "gnome-screenshot",
+                                     NULL);
+  else
+    gdk_pixbuf_save_to_stream_async (screenshot,
+                                     G_OUTPUT_STREAM (os),
+                                     "png", NULL,
+                                     save_pixbuf_ready_cb, dialog,
+                                     "tEXt::Software", "gnome-screenshot",
+                                     NULL);
+
+  g_object_unref (os);
 }
 
 static void
 try_to_save (ScreenshotDialog *dialog)
 {
-  gchar *target_folder, *target_filename, *source_uri;
-  GFile *source_file;
-
-  g_assert (temporary_file);
+  gchar *target_uri;
+  GFile *target_file;
 
   screenshot_dialog_set_busy (dialog, TRUE);
 
-  source_file = g_file_new_for_path (temporary_file);
-  source_uri = g_file_get_uri (source_file);
-
-  target_folder = screenshot_dialog_get_folder (dialog);
-  target_filename = screenshot_dialog_get_filename (dialog);
-
-  g_dbus_connection_call (connection,
-                          "org.gnome.Nautilus",
-                          "/org/gnome/Nautilus",
-                          "org.gnome.Nautilus.FileOperations",
-                          "CopyFile",
-                          g_variant_new ("(ssss)",
-                                         source_uri,
-                                         target_filename,
-                                         target_folder,
-                                         target_filename),
-                          NULL,
-                          G_DBUS_CALL_FLAGS_NONE,
-                          -1,
-                          NULL,
-                          save_callback,
-                          dialog);
-
-  g_object_unref (source_file);
-
-  g_free (source_uri);
-  g_free (target_folder);
-  g_free (target_filename);
+  target_uri = screenshot_dialog_get_uri (dialog);
+  target_file = g_file_new_for_uri (target_uri);
+
+  g_file_create_async (target_file,
+                       G_FILE_CREATE_NONE,
+                       G_PRIORITY_DEFAULT,
+                       NULL,
+                       save_file_create_ready_cb, dialog);
+
+  g_object_unref (target_file);
+  g_free (target_uri);
 }
 
 static void
-save_done_notification (gpointer data)
+screenshot_save_to_clipboard (void)
 {
-  ScreenshotDialog *dialog = data;
-
-  temporary_file = g_strdup (screenshot_save_get_filename ());
-  screenshot_dialog_enable_dnd (dialog);
+  GtkClipboard *clipboard;
 
-  if (save_immediately)
-    {
-      GtkWidget *toplevel;
-
-      toplevel = screenshot_dialog_get_toplevel (dialog);
-      gtk_dialog_response (GTK_DIALOG (toplevel), GTK_RESPONSE_OK);
-    }
+  clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
+                                             GDK_SELECTION_CLIPBOARD);
+  gtk_clipboard_set_image (clipboard, screenshot);
 }
 
 static void
@@ -241,39 +263,21 @@ screenshot_dialog_response_cb (GtkDialog *d,
                                gint response_id,
                                ScreenshotDialog *dialog)
 {
-  if (response_id == GTK_RESPONSE_HELP)
+  switch (response_id)
     {
+    case GTK_RESPONSE_HELP:
       screenshot_display_help (GTK_WINDOW (d));
-    }
-  else if (response_id == GTK_RESPONSE_OK)
-    {
-      if (temporary_file == NULL)
-        {
-          save_immediately = TRUE;
-          screenshot_dialog_set_busy (dialog, TRUE);
-        }
-      else
-        {
-          /* we've saved the temporary file, lets try to copy it to the
-           * correct location.
-           */
-          try_to_save (dialog);
-        }
-    }
-  else if (response_id == SCREENSHOT_RESPONSE_COPY)
-    {
-      GtkClipboard *clipboard;
-      GdkPixbuf    *screenshot;
-
-      clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (d)),
-                                                 GDK_SELECTION_CLIPBOARD);
-      screenshot = screenshot_dialog_get_screenshot (dialog);
-      gtk_clipboard_set_image (clipboard, screenshot);
-    }
-  else /* dialog was canceled */
-    {
+      break;
+    case GTK_RESPONSE_OK:
+      try_to_save (dialog);
+      break;
+    case SCREENSHOT_RESPONSE_COPY:
+      screenshot_save_to_clipboard ();
+      break;
+    default:
       gtk_widget_destroy (GTK_WIDGET (d));
       gtk_main_quit ();
+      break;
     }
 }
                                
@@ -300,7 +304,6 @@ build_filename_ready_cb (GObject *source,
     }
 
   dialog = screenshot_dialog_new (screenshot, save_uri);
-  screenshot_save_start (screenshot, save_done_notification, dialog);
   toplevel = screenshot_dialog_get_toplevel (dialog);
   gtk_widget_show (toplevel);
   
@@ -402,7 +405,6 @@ screenshot_ensure_icc_profile (GdkWindow *window)
   char *icc_profile_filename;
   guchar *icc_profile;
   gsize icc_profile_size;
-  char *icc_profile_base64;
   gboolean ret;
   GError *error = NULL;
 
@@ -424,10 +426,7 @@ screenshot_ensure_icc_profile (GdkWindow *window)
       icc_profile_base64 = g_base64_encode (icc_profile,
                                             icc_profile_size);
 
-      /* use this profile for saving the image */
-      screenshot_set_icc_profile (icc_profile_base64);
       g_free (icc_profile);
-      g_free (icc_profile_base64);
     }
   else
     {
@@ -509,11 +508,7 @@ finish_prepare_screenshot (GdkRectangle *rectangle)
 
   if (screenshot_config->copy_to_clipboard)
     {
-      GtkClipboard *clipboard;
-
-      clipboard = gtk_clipboard_get_for_display (gdk_display_get_default (),
-                                                 GDK_SELECTION_CLIPBOARD);
-      gtk_clipboard_set_image (clipboard, screenshot);
+      screenshot_save_to_clipboard ();
       gtk_main_quit ();
 
       return;
diff --git a/gnome-screenshot/screenshot-dialog.c b/gnome-screenshot/screenshot-dialog.c
index 129b676..d6d954d 100644
--- a/gnome-screenshot/screenshot-dialog.c
+++ b/gnome-screenshot/screenshot-dialog.c
@@ -23,21 +23,17 @@
 
 #include "screenshot-config.h"
 #include "screenshot-dialog.h"
-#include "screenshot-save.h"
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 
 enum {
   TYPE_IMAGE_PNG,
-  TYPE_TEXT_URI_LIST,
-  
   LAST_TYPE
 };
 
 static GtkTargetEntry drag_types[] =
 {
   { "image/png", 0, TYPE_IMAGE_PNG },
-  { "text/uri-list", 0, TYPE_TEXT_URI_LIST },
 };
 
 struct ScreenshotDialog
@@ -140,26 +136,10 @@ drag_data_get (GtkWidget          *widget,
 	       guint               time,
 	       ScreenshotDialog   *dialog)
 {
-  if (info == TYPE_TEXT_URI_LIST)
-    {
-      gchar **uris;
-
-      uris = g_new (gchar *, 2);
-      uris[0] = g_strconcat ("file://",
-                             screenshot_save_get_filename (),
-                             NULL);
-      uris[1] = NULL;
-      
-      gtk_selection_data_set_uris (selection_data, uris);
-    }
-  else if (info == TYPE_IMAGE_PNG)
-    {
-      gtk_selection_data_set_pixbuf (selection_data, dialog->screenshot);
-    }
+  if (info == TYPE_IMAGE_PNG)
+    gtk_selection_data_set_pixbuf (selection_data, dialog->screenshot);
   else
-    {
-      g_warning ("Unknown type %d", info);
-    }
+    g_warning ("Unknown type %d", info);
 }
 
 static void
@@ -249,6 +229,11 @@ screenshot_dialog_new (GdkPixbuf *screenshot,
   g_signal_connect (preview_darea, "button_release_event", G_CALLBACK (on_preview_button_release_event), dialog);
   g_signal_connect (preview_darea, "configure_event", G_CALLBACK (on_preview_configure_event), dialog);
 
+  gtk_drag_source_set (preview_darea,
+		       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+		       drag_types, G_N_ELEMENTS (drag_types),
+		       GDK_ACTION_COPY);
+
   if (screenshot_config->take_window_shot)
     gtk_frame_set_shadow_type (GTK_FRAME (aspect_frame), GTK_SHADOW_NONE);
   else
@@ -286,20 +271,6 @@ screenshot_dialog_focus_entry (ScreenshotDialog *dialog)
   gtk_widget_grab_focus (dialog->filename_entry);
 }
 
-void
-screenshot_dialog_enable_dnd (ScreenshotDialog *dialog)
-{
-  GtkWidget *preview_darea;
-
-  g_return_if_fail (dialog != NULL);
-
-  preview_darea = GTK_WIDGET (gtk_builder_get_object (dialog->ui, "preview_darea"));
-  gtk_drag_source_set (preview_darea,
-		       GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
-		       drag_types, G_N_ELEMENTS (drag_types),
-		       GDK_ACTION_COPY);
-}
-
 GtkWidget *
 screenshot_dialog_get_toplevel (ScreenshotDialog *dialog)
 {
@@ -355,12 +326,6 @@ screenshot_dialog_get_filename (ScreenshotDialog *dialog)
   return tmp;
 }
 
-GdkPixbuf *
-screenshot_dialog_get_screenshot (ScreenshotDialog *dialog)
-{
-  return dialog->screenshot;
-}
-
 void
 screenshot_dialog_set_busy (ScreenshotDialog *dialog,
 			    gboolean          busy)
diff --git a/gnome-screenshot/screenshot-dialog.h b/gnome-screenshot/screenshot-dialog.h
index 92727c8..7741198 100644
--- a/gnome-screenshot/screenshot-dialog.h
+++ b/gnome-screenshot/screenshot-dialog.h
@@ -29,12 +29,10 @@ typedef struct ScreenshotDialog ScreenshotDialog;
 
 ScreenshotDialog *screenshot_dialog_new          (GdkPixbuf        *screenshot,
 						  char             *initial_uri);
-void              screenshot_dialog_enable_dnd   (ScreenshotDialog *dialog);
 GtkWidget        *screenshot_dialog_get_toplevel (ScreenshotDialog *dialog);
 char             *screenshot_dialog_get_uri      (ScreenshotDialog *dialog);
 char             *screenshot_dialog_get_folder   (ScreenshotDialog *dialog);
 char             *screenshot_dialog_get_filename (ScreenshotDialog *dialog);
-GdkPixbuf        *screenshot_dialog_get_screenshot (ScreenshotDialog *dialog);
 void              screenshot_dialog_set_busy     (ScreenshotDialog *dialog,
 						  gboolean          busy);
 void              screenshot_dialog_focus_entry  (ScreenshotDialog *dialog);



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