[gnome-utils] screenshot: use GIO to asynchronously save the screenshot pixbuf
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-utils] screenshot: use GIO to asynchronously save the screenshot pixbuf
- Date: Mon, 26 Sep 2011 20:57:04 +0000 (UTC)
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]