[recipes] Make gr_send_mail async
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Make gr_send_mail async
- Date: Thu, 2 Mar 2017 02:10:18 +0000 (UTC)
commit 575a579042a765e2be92db9099870eb49978a9af
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Mar 1 21:06:48 2017 -0500
Make gr_send_mail async
Implement the full async pattern for this API, and make the
callers fall back to saving the file if sending email fails
with an error.
src/gr-mail.c | 90 +++++++++++++++++++++++++++++++++++-----------
src/gr-mail.h | 14 +++++---
src/gr-recipe-exporter.c | 53 +++++++++++++++++++++++++--
src/gr-shopping-page.c | 59 +++++++++++++++++++++++++++++-
4 files changed, 186 insertions(+), 30 deletions(-)
---
diff --git a/src/gr-mail.c b/src/gr-mail.c
index 1e03035..fdfc282 100644
--- a/src/gr-mail.c
+++ b/src/gr-mail.c
@@ -25,10 +25,12 @@
typedef struct {
GtkWindow *window;
+ char *handle;
char *address;
char *subject;
char *body;
char **attachments;
+ GTask *task;
} MailData;
static void
@@ -36,41 +38,71 @@ mail_data_free (gpointer data)
{
MailData *md = data;
- window_unexport_handle (md->window);
+ if (md->handle) {
+ window_unexport_handle (md->window);
+ g_free (md->handle);
+ }
g_free (md->address);
g_free (md->subject);
g_free (md->body);
g_strfreev (md->attachments);
+ g_object_unref (md->task);
g_free (md);
}
static void
-send_mail_using_mailto (MailData *data)
+launch_uri_done (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ MailData *md = data;
+ GError *error = NULL;
+
+ if (!g_app_info_launch_default_for_uri_finish (result, &error))
+ g_task_return_error (md->task, error);
+ else
+ g_task_return_boolean (md->task, TRUE);
+
+ mail_data_free (data);
+}
+
+static void
+send_mail_using_mailto (MailData *md)
{
g_autoptr(GString) url = NULL;
g_autofree char *encoded_subject = NULL;
g_autofree char *encoded_body = NULL;
int i;
+ GdkDisplay *display;
+ GAppLaunchContext *context;
- encoded_subject = g_uri_escape_string (data->subject, NULL, FALSE);
- encoded_body = g_uri_escape_string (data->body, NULL, FALSE);
+ encoded_subject = g_uri_escape_string (md->subject, NULL, FALSE);
+ encoded_body = g_uri_escape_string (md->body, NULL, FALSE);
url = g_string_new ("mailto:");
- g_string_append_printf (url, "\"%s\"", data->address);
+ g_string_append_printf (url, "\"%s\"", md->address);
g_string_append_printf (url, "?subject=%s", encoded_subject);
g_string_append_printf (url, "&body=%s", encoded_body);
- for (i = 0; data->attachments[i]; i++) {
+ for (i = 0; md->attachments[i]; i++) {
g_autofree char *path = NULL;
- path = g_uri_escape_string (data->attachments[i], NULL, FALSE);
+ path = g_uri_escape_string (md->attachments[i], NULL, FALSE);
g_string_append_printf (url, "&attach=%s", path);
}
- gtk_show_uri_on_window (data->window, url->str, GDK_CURRENT_TIME, NULL);
+ display = gtk_widget_get_display (GTK_WIDGET (md->window));
+ context = G_APP_LAUNCH_CONTEXT (gdk_display_get_app_launch_context (display));
- mail_data_free (data);
+ if (md->handle)
+ g_app_launch_context_setenv (context, "PARENT_WINDOW_ID", md->handle);
+
+ g_app_info_launch_default_for_uri_async (url->str,
+ G_APP_LAUNCH_CONTEXT (context),
+ NULL,
+ launch_uri_done,
+ md);
}
static GDBusProxy *
@@ -91,12 +123,12 @@ get_mail_portal_proxy (void)
}
static void
-callback (GObject *source,
- GAsyncResult *result,
- gpointer data)
+compose_mail_done (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
{
g_autoptr(GVariant) reply = NULL;
- g_autoptr(GError) error = NULL;
+ GError *error = NULL;
MailData *md = data;
reply = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
@@ -106,9 +138,11 @@ callback (GObject *source,
send_mail_using_mailto (md);
return;
}
- else if (error) {
- g_message ("Sending mail using Email portal failed: %s", error->message);
- }
+
+ if (error)
+ g_task_return_error (md->task, error);
+ else
+ g_task_return_boolean (md->task, TRUE);
mail_data_free (md);
}
@@ -122,6 +156,8 @@ window_handle_exported (GtkWindow *window,
GVariantBuilder opt_builder;
GDBusProxy *proxy;
+ md->handle = g_strdup (handle_str);
+
proxy = get_mail_portal_proxy ();
if (proxy == NULL) {
@@ -134,7 +170,8 @@ window_handle_exported (GtkWindow *window,
g_variant_builder_add (&opt_builder, "{sv}", "address", g_variant_new_string (md->address));
g_variant_builder_add (&opt_builder, "{sv}", "subject", g_variant_new_string (md->subject));
g_variant_builder_add (&opt_builder, "{sv}", "body", g_variant_new_string (md->body));
- g_variant_builder_add (&opt_builder, "{sv}", "attachments", g_variant_new_strv ((const char * const
*)md->attachments, -1));
+ if (md->attachments)
+ g_variant_builder_add (&opt_builder, "{sv}", "attachments", g_variant_new_strv ((const char
* const *)md->attachments, -1));
g_dbus_proxy_call (proxy,
"ComposeEmail",
@@ -144,7 +181,7 @@ window_handle_exported (GtkWindow *window,
G_DBUS_CALL_FLAGS_NONE,
G_MAXINT,
NULL,
- callback,
+ compose_mail_done,
data);
}
@@ -153,16 +190,27 @@ gr_send_mail (GtkWindow *window,
const char *address,
const char *subject,
const char *body,
- const char **attachments)
+ const char **attachments,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
MailData *data;
+ const char *empty_strv[1] = { NULL };
- data = g_new (MailData, 1);
+ data = g_new0 (MailData, 1);
data->window = window;
data->address = g_strdup (address ? address : "");
data->subject = g_strdup (subject ? subject : "");
data->body = g_strdup (body ? body : "");
- data->attachments = g_strdupv ((char **)attachments);
+ data->attachments = g_strdupv (attachments ? (char **)attachments : (char **)empty_strv);
+ data->task = g_task_new (NULL, NULL, callback, user_data);
window_export_handle (window, window_handle_exported, data);
}
+
+gboolean
+gr_send_mail_finish (GAsyncResult *result,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/src/gr-mail.h b/src/gr-mail.h
index 623fd37..0950226 100644
--- a/src/gr-mail.h
+++ b/src/gr-mail.h
@@ -24,10 +24,14 @@
G_BEGIN_DECLS
-void gr_send_mail (GtkWindow *window,
- const char *address,
- const char *subject,
- const char *body,
- const char **attachments);
+void gr_send_mail (GtkWindow *window,
+ const char *address,
+ const char *subject,
+ const char *body,
+ const char **attachments,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gr_send_mail_finish (GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/gr-recipe-exporter.c b/src/gr-recipe-exporter.c
index 123e7f2..f6d6ff8 100644
--- a/src/gr-recipe-exporter.c
+++ b/src/gr-recipe-exporter.c
@@ -119,6 +119,53 @@ cleanup_export (GrRecipeExporter *exporter)
}
#ifdef ENABLE_AUTOAR
+
+static void
+file_chooser_response (GtkNativeDialog *self,
+ int response_id,
+ GrRecipeExporter *exporter)
+{
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ g_autoptr(GFile) file = NULL;
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (self));
+ g_file_copy_async (exporter->dest, file, 0, 0, NULL, NULL, NULL, NULL, NULL);
+ }
+
+ gtk_native_dialog_destroy (self);
+
+ cleanup_export (exporter);
+}
+
+static void
+mail_done (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GrRecipeExporter *exporter = data;
+ g_autoptr(GError) error = NULL;
+
+ if (!gr_send_mail_finish (result, &error)) {
+ GObject *file_chooser;
+
+ g_message ("Sending mail failed: %s", error->message);
+
+ file_chooser = (GObject *)gtk_file_chooser_native_new (_("Save the exported recipe"),
+ GTK_WINDOW (exporter->window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("Save"),
+ _("Canel"));
+ gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (file_chooser), TRUE);
+
+ g_signal_connect (file_chooser, "response", G_CALLBACK (file_chooser_response), exporter);
+
+ gtk_native_dialog_show (GTK_NATIVE_DIALOG (file_chooser));
+ return;
+ }
+
+ cleanup_export (exporter);
+}
+
static void
completed_cb (AutoarCompressor *compressor,
GrRecipeExporter *exporter)
@@ -168,9 +215,9 @@ completed_cb (AutoarCompressor *compressor,
attachments[0] = path;
attachments[1] = NULL;
- gr_send_mail (GTK_WINDOW (exporter->window), address, subject, body, attachments);
-
- cleanup_export (exporter);
+ gr_send_mail (GTK_WINDOW (exporter->window),
+ address, subject, body, attachments,
+ mail_done, exporter);
}
static void
diff --git a/src/gr-shopping-page.c b/src/gr-shopping-page.c
index d4ffce2..b4d99f1 100644
--- a/src/gr-shopping-page.c
+++ b/src/gr-shopping-page.c
@@ -674,6 +674,61 @@ print_list (GrShoppingPage *page)
g_list_free_full (items, item_free);
}
+
+static void
+file_chooser_response (GtkNativeDialog *self,
+ int response_id,
+ GrShoppingPage *page)
+{
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ GList *recipes, *items;
+ g_autoptr(GFile) file = NULL;
+ g_autofree char *text = NULL;
+
+ recipes = get_recipes (page);
+ items = get_ingredients (page);
+
+ text = gr_shopping_list_format (recipes, items);
+
+ g_list_free_full (recipes, g_object_unref);
+ g_list_free_full (items, item_free);
+
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (self));
+ g_file_replace_contents (file, text, -1, NULL, FALSE, 0, NULL, NULL, NULL);
+ }
+
+ gtk_native_dialog_destroy (self);
+}
+
+static void
+mail_done (GObject *source,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GrShoppingPage *page = data;
+ g_autoptr(GError) error = NULL;
+
+ if (!gr_send_mail_finish (result, &error)) {
+ GObject *file_chooser;
+ GtkWidget *window;
+
+ g_message ("Sending mail failed: %s", error->message);
+
+ window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
+ file_chooser = (GObject *)gtk_file_chooser_native_new (_("Save the shopping list"),
+ GTK_WINDOW (window),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ _("Save"),
+ _("Canel"));
+ gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (file_chooser), TRUE);
+
+ g_signal_connect (file_chooser, "response", G_CALLBACK (file_chooser_response), page);
+
+ gtk_native_dialog_show (GTK_NATIVE_DIALOG (file_chooser));
+ return;
+ }
+}
+
static void
share_list (GrShoppingPage *page)
{
@@ -688,7 +743,9 @@ share_list (GrShoppingPage *page)
window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
- gr_send_mail (GTK_WINDOW (window), NULL, _("Shopping List"), text, NULL);
+ gr_send_mail (GTK_WINDOW (window),
+ NULL, _("Shopping List"), text, NULL,
+ mail_done, page);
g_list_free_full (recipes, g_object_unref);
g_list_free_full (items, item_free);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]