aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2013-07-27 22:31:24 +0800
committerMatthew Barnes <mbarnes@redhat.com>2013-07-28 09:24:01 +0800
commit826372c35155cb47f940905e27b304e9ef63441d (patch)
treeee995baeb76eb19abe760a0baa32aada72d141e8
parent3eda7a50de7059e7898944d74ab1fc7c707e089b (diff)
downloadgsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.tar
gsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.tar.gz
gsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.tar.bz2
gsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.tar.lz
gsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.tar.xz
gsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.tar.zst
gsoc2013-evolution-826372c35155cb47f940905e27b304e9ef63441d.zip
Add e_web_view_cursor_image_save().
Prompts the user to choose a destination file and then asynchronously saves the image under the cursor to the destination file.
-rw-r--r--doc/reference/evolution-util/evolution-util-sections.txt1
-rw-r--r--e-util/e-web-view.c235
-rw-r--r--e-util/e-web-view.h1
3 files changed, 237 insertions, 0 deletions
diff --git a/doc/reference/evolution-util/evolution-util-sections.txt b/doc/reference/evolution-util/evolution-util-sections.txt
index ed4a25dd3b..f4878fd4fd 100644
--- a/doc/reference/evolution-util/evolution-util-sections.txt
+++ b/doc/reference/evolution-util/evolution-util-sections.txt
@@ -4411,6 +4411,7 @@ e_web_view_update_actions
e_web_view_get_selection_html
e_web_view_update_fonts
e_web_view_cursor_image_copy
+e_web_view_cursor_image_save
e_web_view_request
e_web_view_request_finish
e_web_view_install_request_handler
diff --git a/e-util/e-web-view.c b/e-util/e-web-view.c
index 45b48c4e19..a762c45513 100644
--- a/e-util/e-web-view.c
+++ b/e-util/e-web-view.c
@@ -75,6 +75,8 @@ struct _EWebViewPrivate {
};
struct _AsyncContext {
+ EActivity *activity;
+ GFile *destination;
GInputStream *input_stream;
};
@@ -151,6 +153,8 @@ G_DEFINE_TYPE_WITH_CODE (
static void
async_context_free (AsyncContext *async_context)
{
+ g_clear_object (&async_context->activity);
+ g_clear_object (&async_context->destination);
g_clear_object (&async_context->input_stream);
g_slice_free (AsyncContext, async_context);
@@ -2824,6 +2828,237 @@ e_web_view_cursor_image_copy (EWebView *web_view)
}
}
+/* Helper for e_web_view_cursor_image_save() */
+static void
+web_view_cursor_image_save_splice_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EActivity *activity;
+ EAlertSink *alert_sink;
+ AsyncContext *async_context;
+ GError *local_error = NULL;
+
+ async_context = (AsyncContext *) user_data;
+
+ activity = async_context->activity;
+ alert_sink = e_activity_get_alert_sink (activity);
+
+ g_output_stream_splice_finish (
+ G_OUTPUT_STREAM (source_object), result, &local_error);
+
+ if (e_activity_handle_cancellation (activity, local_error)) {
+ g_error_free (local_error);
+
+ } else if (local_error != NULL) {
+ e_alert_submit (
+ alert_sink,
+ "widgets:no-image-save",
+ local_error->message, NULL);
+ g_error_free (local_error);
+
+ } else {
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
+ }
+
+ async_context_free (async_context);
+}
+
+/* Helper for e_web_view_cursor_image_save() */
+static void
+web_view_cursor_image_save_replace_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EActivity *activity;
+ EAlertSink *alert_sink;
+ GCancellable *cancellable;
+ GFileOutputStream *output_stream;
+ AsyncContext *async_context;
+ GError *local_error = NULL;
+
+ async_context = (AsyncContext *) user_data;
+
+ activity = async_context->activity;
+ alert_sink = e_activity_get_alert_sink (activity);
+ cancellable = e_activity_get_cancellable (activity);
+
+ output_stream = g_file_replace_finish (
+ G_FILE (source_object), result, &local_error);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((output_stream != NULL) && (local_error == NULL)) ||
+ ((output_stream == NULL) && (local_error != NULL)));
+
+ if (e_activity_handle_cancellation (activity, local_error)) {
+ g_error_free (local_error);
+ async_context_free (async_context);
+
+ } else if (local_error != NULL) {
+ e_alert_submit (
+ alert_sink,
+ "widgets:no-image-save",
+ local_error->message, NULL);
+ g_error_free (local_error);
+ async_context_free (async_context);
+
+ } else {
+ g_output_stream_splice_async (
+ G_OUTPUT_STREAM (output_stream),
+ async_context->input_stream,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+ G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ web_view_cursor_image_save_splice_cb,
+ async_context);
+ }
+
+ g_clear_object (&output_stream);
+}
+
+/* Helper for e_web_view_cursor_image_save() */
+static void
+web_view_cursor_image_save_request_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EActivity *activity;
+ EAlertSink *alert_sink;
+ GCancellable *cancellable;
+ GInputStream *input_stream;
+ AsyncContext *async_context;
+ GError *local_error = NULL;
+
+ async_context = (AsyncContext *) user_data;
+
+ activity = async_context->activity;
+ alert_sink = e_activity_get_alert_sink (activity);
+ cancellable = e_activity_get_cancellable (activity);
+
+ input_stream = e_web_view_request_finish (
+ E_WEB_VIEW (source_object), result, &local_error);
+
+ /* Sanity check. */
+ g_return_if_fail (
+ ((input_stream != NULL) && (local_error == NULL)) ||
+ ((input_stream == NULL) && (local_error != NULL)));
+
+ if (e_activity_handle_cancellation (activity, local_error)) {
+ g_error_free (local_error);
+ async_context_free (async_context);
+
+ } else if (local_error != NULL) {
+ e_alert_submit (
+ alert_sink,
+ "widgets:no-image-save",
+ local_error->message, NULL);
+ g_error_free (local_error);
+ async_context_free (async_context);
+
+ } else {
+ async_context->input_stream = g_object_ref (input_stream);
+
+ /* Open an output stream to the destination file. */
+ g_file_replace_async (
+ async_context->destination,
+ NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ web_view_cursor_image_save_replace_cb,
+ async_context);
+ }
+
+ g_clear_object (&input_stream);
+}
+
+/**
+ * e_web_view_cursor_image_save:
+ * @web_view: an #EWebView
+ *
+ * Prompts the user to choose a destination file and then asynchronously
+ * saves the image under the cursor to the destination file.
+ *
+ * This function triggers a #EWebView::new-activity signal emission so
+ * the asynchronous operation can be tracked and/or cancelled.
+ **/
+void
+e_web_view_cursor_image_save (EWebView *web_view)
+{
+ GtkFileChooser *file_chooser;
+ GFile *destination = NULL;
+ GtkWidget *dialog;
+ gchar *suggestion;
+ gpointer toplevel;
+
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ if (web_view->priv->cursor_image_src == NULL)
+ return;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
+ toplevel = gtk_widget_is_toplevel (toplevel) ? toplevel : NULL;
+
+ dialog = gtk_file_chooser_dialog_new (
+ _("Save Image"), toplevel,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
+
+ gtk_dialog_set_default_response (
+ GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ file_chooser = GTK_FILE_CHOOSER (dialog);
+ gtk_file_chooser_set_local_only (file_chooser, FALSE);
+ gtk_file_chooser_set_do_overwrite_confirmation (file_chooser, TRUE);
+
+ suggestion = e_web_view_suggest_filename (
+ web_view, web_view->priv->cursor_image_src);
+
+ if (suggestion != NULL) {
+ gtk_file_chooser_set_current_name (file_chooser, suggestion);
+ g_free (suggestion);
+ }
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ destination = gtk_file_chooser_get_file (file_chooser);
+
+ gtk_widget_destroy (dialog);
+
+ if (destination != NULL) {
+ EActivity *activity;
+ GCancellable *cancellable;
+ AsyncContext *async_context;
+ gchar *text;
+ gchar *uri;
+
+ activity = e_web_view_new_activity (web_view);
+ cancellable = e_activity_get_cancellable (activity);
+
+ uri = g_file_get_uri (destination);
+ text = g_strdup_printf (_("Saving image to '%s'"), uri);
+ e_activity_set_text (activity, text);
+ g_free (text);
+ g_free (uri);
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->activity = g_object_ref (activity);
+ async_context->destination = g_object_ref (destination);
+
+ e_web_view_request (
+ web_view,
+ web_view->priv->cursor_image_src,
+ cancellable,
+ web_view_cursor_image_save_request_cb,
+ async_context);
+
+ g_object_unref (activity);
+ g_object_unref (destination);
+ }
+}
+
/* Helper for e_web_view_request() */
static void
web_view_request_send_cb (GObject *source_object,
diff --git a/e-util/e-web-view.h b/e-util/e-web-view.h
index 3f7b4e10b5..2f99b7a248 100644
--- a/e-util/e-web-view.h
+++ b/e-util/e-web-view.h
@@ -186,6 +186,7 @@ void e_web_view_update_actions (EWebView *web_view);
gchar * e_web_view_get_selection_html (EWebView *web_view);
void e_web_view_update_fonts (EWebView *web_view);
void e_web_view_cursor_image_copy (EWebView *web_view);
+void e_web_view_cursor_image_save (EWebView *web_view);
void e_web_view_request (EWebView *web_view,
const gchar *uri,
GCancellable *cancellable,