[recipes/todoist-3] Creates dialog for sharing ingredients. Sends the ingredients list to todoist if account is set up f
- From: Ekta Nandwani <ektan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes/todoist-3] Creates dialog for sharing ingredients. Sends the ingredients list to todoist if account is set up f
- Date: Tue, 8 Aug 2017 03:44:57 +0000 (UTC)
commit 9ba4de8a10e52f92c7217d37ad12f9622c65b608
Author: Ekta Nandwani <mailnandwaniekta gmail com>
Date: Sat Jul 1 19:17:49 2017 +0530
Creates dialog for sharing ingredients.
Sends the ingredients list to todoist if account is set up for the same.
data/gschemas.compiled | Bin 0 -> 904 bytes
meson.build | 3 +
src/gr-ingredients-exporter.c | 536 ++++++++++++++++++++++++++++++++++++
src/gr-ingredients-exporter.h | 37 +++
src/gr-recipe-exporter.c | 61 +++--
src/gr-shopping-page.c | 32 ++-
src/gr-shopping-page.h | 3 +
src/gr-shopping-page.ui | 2 +-
src/ingredients-exporter-dialog.ui | 226 +++++++++++++++
src/meson.build | 1 +
src/recipes.gresource.xml | 1 +
11 files changed, 869 insertions(+), 33 deletions(-)
---
diff --git a/data/gschemas.compiled b/data/gschemas.compiled
new file mode 100644
index 0000000..27bfa4e
Binary files /dev/null and b/data/gschemas.compiled differ
diff --git a/meson.build b/meson.build
index 5afc27b..432a672 100644
--- a/meson.build
+++ b/meson.build
@@ -82,6 +82,9 @@ endif
deps = [ dependency('gtk+-3.0', version : '>=3.22'),
dependency('gmodule-export-2.0'),
dependency('libsoup-2.4'),
+ dependency('goa-1.0'),
+ dependency('rest-0.7'),
+ dependency('json-glib-1.0'),
autoar_dep,
gspell_dep,
canberra_dep,
diff --git a/src/gr-ingredients-exporter.c b/src/gr-ingredients-exporter.c
new file mode 100644
index 0000000..448a98f
--- /dev/null
+++ b/src/gr-ingredients-exporter.c
@@ -0,0 +1,536 @@
+/* gr-ingredients-exporter.c:
+ *
+ * Copyright (C) 2017 Ekta Nandwani
+ *
+ * Licensed under the GNU General Public License Version 3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <goa/goa.h>
+#include <rest/oauth2-proxy.h>
+#include <json-glib/json-glib.h>
+
+#include "gr-ingredients-exporter.h"
+#include "gr-recipe-store.h"
+#include "gr-shopping-page.h"
+
+#define TODOIST_URL "https://todoist.com/API/v7/sync"
+
+static void get_project_id (GrIngredientsExporter *exporter);
+
+struct _GrIngredientsExporter
+{
+ GObject parent_instance;
+ GtkWindow *window;
+
+ gchar *access_token;
+ GoaObject *account_object;
+ const gchar *sync_token;
+ glong project_id;
+
+ GtkWidget *export_button;
+ GtkWidget *cancel_button;
+ GtkWidget *back_button;
+ GtkWidget *todoist_row;
+ GtkWidget *accounts_box;
+ GtkWidget *providers_box;
+ GtkWidget *dialog_stack;
+ GtkWidget *header_start_stack;
+ GtkWidget *header;
+ GtkWidget *providers_list;
+ GtkWidget *accounts_list;
+ GtkWidget *account_row_selected;
+
+ GList *ingredients;
+};
+
+
+G_DEFINE_TYPE (GrIngredientsExporter, gr_ingredients_exporter, G_TYPE_OBJECT);
+
+static void
+gr_ingredients_exporter_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gr_ingredients_exporter_parent_class)->finalize (object);
+
+}
+
+
+static void
+gr_ingredients_exporter_class_init (GrIngredientsExporterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gr_ingredients_exporter_finalize;
+}
+
+static void
+gr_ingredients_exporter_init (GrIngredientsExporter *self)
+{
+}
+
+GrIngredientsExporter *
+gr_ingredients_exporter_new (GtkWindow *parent)
+{
+ GrIngredientsExporter *exporter;
+
+ exporter = g_object_new (GR_TYPE_INGREDIENTS_EXPORTER, NULL);
+ exporter->window = parent;
+ return exporter;
+}
+
+static gboolean
+get_ingredients_list (GrIngredientsExporter *exporter)
+{
+ GtkWidget *shopping_page;
+
+ shopping_page = gr_shopping_page_new ();
+ gr_shopping_page_populate (GR_SHOPPING_PAGE (shopping_page));
+ exporter->ingredients = get_ingredients (GR_SHOPPING_PAGE (shopping_page));
+
+ if (exporter->ingredients)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+switch_dialog_contents (GrIngredientsExporter *exporter)
+{
+ if (gtk_stack_get_visible_child (GTK_STACK (exporter->dialog_stack)) ==
exporter->accounts_box) {
+ gtk_widget_set_visible (exporter->export_button, FALSE);
+ gtk_stack_set_visible_child_name (GTK_STACK (exporter->dialog_stack),
"providers_box");
+ gtk_stack_set_visible_child_name (GTK_STACK (exporter->header_start_stack),
"back");
+ gtk_header_bar_set_title (GTK_HEADER_BAR (exporter->header), _("Add
Account"));
+ }
+ else {
+ gtk_widget_set_visible (exporter->export_button, TRUE);
+ gtk_stack_set_visible_child (GTK_STACK (exporter->dialog_stack),
exporter->accounts_box);
+ gtk_stack_set_visible_child_name (GTK_STACK (exporter->header_start_stack),
"cancel_button");
+ gtk_header_bar_set_title (GTK_HEADER_BAR (exporter->header), _("Export
Ingredients"));
+ }
+}
+
+static void
+export_shopping_list_callback (RestProxyCall *call, GError *error,
+ GObject *obj, GrIngredientsExporter *exporter)
+{
+ JsonObject *object;
+ JsonParser *parser;
+ GError *parse_error;
+ const gchar *payload;
+ guint status_code;
+ gsize payload_length;
+ const gchar *sync_token;
+
+ parse_error = NULL;
+ status_code = rest_proxy_call_get_status_code (call);
+ parser = json_parser_new ();
+
+ if (status_code != 200) {
+ g_warning("Couldn't export shopping list");
+ goto out;
+ }
+
+ payload = rest_proxy_call_get_payload (call);
+ payload_length = rest_proxy_call_get_payload_length (call);
+
+ if (!json_parser_load_from_data (parser, payload, payload_length, &parse_error)) {
+ g_clear_error (&parse_error);
+ goto out;
+ }
+
+ object = json_node_dup_object (json_parser_get_root (parser));
+
+ if (!object) {
+ g_warning("Export returned empty json");
+ }
+ sync_token = json_object_get_string_member (object, "sync_token");
+ exporter->sync_token = sync_token;
+
+ out:
+ g_object_unref (parser);
+}
+
+
+
+static void
+export_shopping_list (GrIngredientsExporter *exporter)
+{
+
+ RestProxy *proxy;
+ RestProxyCall *call;
+ GError *error;
+
+ GList *list;
+
+ GString *commands;
+ commands = g_string_new ("");
+ error = NULL;
+ GString *commands_arg;
+ gboolean got_ingredients;
+
+ got_ingredients = get_ingredients_list (exporter);
+
+ if (got_ingredients) {
+ for (list = exporter->ingredients; list != NULL; list = list->next) {
+ GString *s;
+
+ ShoppingListItem *item = list->data;
+ s = g_string_new ("");
+ g_string_append_printf (s, "%s %s", item->amount, item->name);
+ gchar *uuid = g_uuid_string_random();
+ gchar *temp_id = g_uuid_string_random();
+
+ g_string_append_printf (commands, "{\"type\": \"item_add\",
\"temp_id\":\"%s\",\"uuid\":\"%s\", "
+ "\"args\":{\"content\":\"%s\",\"project_id\":%ld}},",
+ temp_id, uuid,
+ s->str, exporter->project_id);
+ }
+ }
+
+ commands = g_string_truncate (commands, commands->len-1);
+ commands_arg = g_string_new ("[");
+ g_string_append_printf (commands_arg, "%s]", commands->str);
+
+ proxy = rest_proxy_new (TODOIST_URL, FALSE);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "POST");
+ rest_proxy_call_add_header (call, "content-type", "application/x-www-form-urlencoded");
+ rest_proxy_call_add_param (call, "token", exporter->access_token);
+
+ if (!exporter->sync_token)
+ rest_proxy_call_add_param (call, "sync_token", "\'*\'");
+ else
+ rest_proxy_call_add_param (call, "sync_token", exporter->sync_token);
+
+ rest_proxy_call_add_param (call, "commands", commands_arg->str);
+
+ if (!rest_proxy_call_async (call, (RestProxyCallAsyncCallback) export_shopping_list_callback,
+ NULL, exporter, &error))
+ {
+ g_warning ("Couldn't execute RestProxyCall");
+ }
+
+ g_object_unref (proxy);
+ g_object_unref (call);
+
+}
+
+static void
+cancel_export (GrIngredientsExporter *exporter)
+{
+ g_print ("cancel_export\n");
+}
+
+static void
+get_selected_account (GtkListBox *list, GrIngredientsExporter *exporter)
+{
+ exporter->account_row_selected = GTK_WIDGET (gtk_list_box_get_selected_row (list));
+}
+
+static gboolean
+get_todoist_account (GrIngredientsExporter *exporter)
+{
+
+ GoaClient *client;
+ GList *accounts, *l;
+ GoaAccount *account;
+ GError *error;
+
+ client = goa_client_new_sync (NULL, &error);
+
+ if (!client) {
+ g_error ("Could not create GoaClient: %s", error->message);
+ return 0;
+ }
+
+ accounts = goa_client_get_accounts (client);
+ for (l = accounts; l != NULL; l = l->next) {
+ const gchar *provider_type;
+
+ account = goa_object_get_account (GOA_OBJECT (l->data));
+ provider_type = goa_account_get_provider_name (account);
+
+ if (g_strcmp0 (provider_type, "Todoist") == 0) {
+ exporter->account_object = GOA_OBJECT(l->data);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void get_access_token (GrIngredientsExporter *exporter)
+{
+
+ gchar *access_token;
+ GoaOAuth2Based *oauth2 = NULL;
+ GError *error;
+
+ error = NULL;
+ oauth2 = goa_object_get_oauth2_based (GOA_OBJECT (exporter->account_object));
+
+ if (!goa_oauth2_based_call_get_access_token_sync (oauth2, &access_token, NULL, NULL, &error))
{
+ g_warning ("Access token not found!");
+ }
+ exporter->access_token = access_token;
+
+}
+
+static void
+add_project_id (GrIngredientsExporter *exporter)
+{
+
+ RestProxy *proxy;
+ RestProxyCall *call;
+ gchar *uuid, *temp_id;
+ guint status_code;
+ GError *error;
+
+ JsonObject *object;
+ JsonParser *parser;
+ GError *parse_error;
+ const gchar *payload;
+ JsonArray *projects;
+
+ gsize payload_length;
+ const gchar *sync_token;
+
+ GList *lists;
+ GList *l;
+ GString *project_add_commands;
+
+ project_add_commands = g_string_new ("");
+ uuid = g_uuid_string_random ();
+ temp_id = g_uuid_string_random ();
+ proxy = rest_proxy_new (TODOIST_URL, FALSE);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "POST");
+ rest_proxy_call_add_header (call, "content-type", "application/x-www-form-urlencoded");
+ rest_proxy_call_add_param (call, "token", exporter->access_token);
+ rest_proxy_call_add_param (call, "resource_types", "[\"projects\"]" );
+
+
+ if (!exporter->sync_token)
+ rest_proxy_call_add_param (call, "sync_token", "\'*\'");
+ else
+ rest_proxy_call_add_param (call, "sync_token", exporter->sync_token);
+
+ g_string_append_printf (project_add_commands, "[{\"type\": \"project_add\",
\"temp_id\":\"%s\",\"uuid\":\"%s\", "
+ "\"args\":{\"name\":\"Shopping List from Recipes\"}}]",
+ temp_id, uuid);
+
+ rest_proxy_call_add_param (call, "commands",project_add_commands->str);
+
+ if (!rest_proxy_call_sync (call, &error)) {
+ g_clear_error (&error);
+ }
+
+ status_code = rest_proxy_call_get_status_code (call);
+
+ if (status_code != 200) {
+ g_warning("status code %d", status_code);
+ }
+
+ parser = json_parser_new ();
+ payload = rest_proxy_call_get_payload (call);
+ payload_length = rest_proxy_call_get_payload_length (call);
+
+ if (!json_parser_load_from_data (parser, payload, payload_length, &parse_error)) {
+ g_clear_error (&parse_error);
+ g_warning("Couldnt load payload");
+ }
+
+ object = json_node_dup_object (json_parser_get_root (parser));
+
+ if (!object)
+ g_warning("No Data found");
+
+ projects = json_object_get_array_member (object, "projects");
+
+ lists = json_array_get_elements (projects);
+ sync_token = json_object_get_string_member(object, "sync_token");
+ exporter->sync_token = sync_token;
+
+ for (l = lists; l != NULL; l = l->next) {
+ JsonObject *object;
+ const gchar *name;
+ double id;
+
+ object = json_node_get_object (l->data);
+ name = json_object_get_string_member (object, "name");
+
+ if (strcmp (name, "Shopping List from Recipes") == 0) {
+ id = json_object_get_double_member (object, "id");
+ (exporter->project_id) = (glong) id;
+ }
+ }
+}
+
+static void
+get_project_id (GrIngredientsExporter *exporter)
+{
+ RestProxy *proxy;
+ RestProxyCall *call;
+ GError *error;
+
+ JsonObject *object;
+ JsonParser *parser;
+ GError *parse_error;
+ const gchar *payload;
+ guint status_code;
+ gsize payload_length;
+ const gchar *sync_token;
+ GList *lists;
+ GList *l;
+ JsonArray *projects;
+
+
+ proxy = rest_proxy_new (TODOIST_URL, FALSE);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "POST");
+ rest_proxy_call_add_header (call, "content-type", "application/x-www-form-urlencoded");
+ rest_proxy_call_add_param (call, "token", exporter->access_token);
+
+ if (!exporter->sync_token)
+ rest_proxy_call_add_param (call, "sync_token", "\'*\'");
+ else
+ rest_proxy_call_add_param (call, "sync_token", exporter->sync_token);
+
+ rest_proxy_call_add_param (call, "resource_types", "[\"projects\"]");
+
+ if (!rest_proxy_call_sync (call, &error)) {
+ g_clear_error (&error);
+ }
+
+ g_object_unref(proxy);
+
+ parse_error = NULL;
+ status_code = rest_proxy_call_get_status_code (call);
+ parser = json_parser_new ();
+
+ if (status_code != 200) {
+ g_warning ("Couldn't export shopping list");
+ }
+
+ payload = rest_proxy_call_get_payload (call);
+ payload_length = rest_proxy_call_get_payload_length (call);
+
+ if (!json_parser_load_from_data (parser, payload, payload_length, &parse_error)) {
+ g_clear_error (&parse_error);
+ }
+
+ object = json_node_dup_object (json_parser_get_root (parser));
+ if (!object)
+ g_warning("No Data found");
+
+ projects = json_object_get_array_member (object, "projects");
+
+ lists = json_array_get_elements (projects);
+
+ for (l = lists; l != NULL; l = l->next) {
+ JsonObject *object;
+ const gchar *name;
+ double id;
+
+ object = json_node_get_object (l->data);
+
+ name = json_object_get_string_member (object, "name");
+
+ if (strcmp (name, "Shopping List from Recipes") == 0) {
+ id = json_object_get_double_member (object, "id");
+ (exporter->project_id) = (glong) id;
+ goto export;
+ }
+ }
+
+ if (!exporter->project_id)
+ add_project_id (exporter);
+
+ sync_token = json_object_get_string_member (object, "sync_token");
+ exporter->sync_token = sync_token;
+
+ export:
+ if (exporter->project_id) {
+ export_shopping_list (exporter);
+ }
+}
+
+static void
+initialize_export (GrIngredientsExporter *exporter)
+{
+
+ if (exporter->account_row_selected == exporter->todoist_row) {
+ get_access_token (exporter);
+ if (!exporter->project_id) {
+ get_project_id (exporter);
+ }
+ }
+ else {
+ GtkWidget *shopping_page;
+
+ shopping_page = gr_shopping_page_new ();
+ gr_shopping_page_populate (GR_SHOPPING_PAGE (shopping_page));
+ share_list (GR_SHOPPING_PAGE (shopping_page));
+ }
+}
+
+
+static void
+show_export_dialog (GrIngredientsExporter *exporter)
+{
+ g_autoptr(GtkBuilder) builder = NULL;
+ GtkWidget *dialog;
+ GObject *add_service;
+
+ builder = gtk_builder_new_from_resource ("/org/gnome/Recipes/ingredients-exporter-dialog.ui");
+ dialog = GTK_WIDGET (gtk_builder_get_object (builder, "dialog"));
+ exporter->todoist_row = GTK_WIDGET (gtk_builder_get_object (builder, "todoist_account_row"));
+ add_service = gtk_builder_get_object (builder, "add_service");
+
+ exporter->export_button = GTK_WIDGET (gtk_builder_get_object (builder, "export_button"));
+ exporter->cancel_button = GTK_WIDGET (gtk_builder_get_object (builder, "cancel_button"));
+ exporter->back_button = GTK_WIDGET (gtk_builder_get_object (builder, "back_button"));
+ exporter->accounts_box = GTK_WIDGET (gtk_builder_get_object (builder, "accounts_box"));
+ exporter->providers_box = GTK_WIDGET (gtk_builder_get_object (builder, "providers_box"));
+ exporter->dialog_stack = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_stack"));
+ exporter->header_start_stack = GTK_WIDGET (gtk_builder_get_object (builder, "header_start_stack"));
+ exporter->header = GTK_WIDGET (gtk_builder_get_object (builder, "header"));
+ exporter->providers_list = GTK_WIDGET (gtk_builder_get_object (builder, "providers_list"));
+ exporter->accounts_list = GTK_WIDGET (gtk_builder_get_object (builder, "accounts_list"));
+
+ g_signal_connect_swapped (add_service, "activate-link", G_CALLBACK (switch_dialog_contents),
exporter);
+ g_signal_connect_swapped (exporter->back_button, "clicked", G_CALLBACK (switch_dialog_contents),
exporter);
+ g_signal_connect_swapped (exporter->export_button, "clicked", G_CALLBACK (initialize_export),
exporter);
+ g_signal_connect (exporter->cancel_button, "clicked", G_CALLBACK (cancel_export), exporter);
+ g_signal_connect (exporter->accounts_list, "selected-rows-changed", G_CALLBACK
(get_selected_account), exporter);
+
+ if (get_todoist_account (exporter)) {
+ gtk_widget_set_visible (exporter->todoist_row, TRUE);
+ }
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (exporter->window));
+ gtk_widget_show (dialog);
+}
+
+void
+gr_ingredients_exporter_export (GrIngredientsExporter *exporter)
+{
+ show_export_dialog (exporter);
+}
diff --git a/src/gr-ingredients-exporter.h b/src/gr-ingredients-exporter.h
new file mode 100644
index 0000000..6c83d54
--- /dev/null
+++ b/src/gr-ingredients-exporter.h
@@ -0,0 +1,37 @@
+/* gr-ingredients-exporter.h:
+ *
+ * Copyright (C) 2017 Ekta Nandwani
+ *
+ * Licensed under the GNU General Public License Version 3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include "gr-recipe.h"
+#include "gr-shopping-list-printer.h"
+
+G_BEGIN_DECLS
+
+#define GR_TYPE_INGREDIENTS_EXPORTER (gr_ingredients_exporter_get_type())
+
+G_DECLARE_FINAL_TYPE (GrIngredientsExporter, gr_ingredients_exporter, GR, INGREDIENTS_EXPORTER, GObject)
+
+GrIngredientsExporter *gr_ingredients_exporter_new (GtkWindow *window);
+
+void gr_ingredients_exporter_export (GrIngredientsExporter *exporter);
+
+G_END_DECLS
\ No newline at end of file
diff --git a/src/gr-recipe-exporter.c b/src/gr-recipe-exporter.c
index 7131855..13a7d7a 100644
--- a/src/gr-recipe-exporter.c
+++ b/src/gr-recipe-exporter.c
@@ -1,23 +1,23 @@
-/* gr-recipe-exporter.c:
- *
- * Copyright (C) 2016 Matthias Clasen <mclasen redhat com>
- *
- * Licensed under the GNU General Public License Version 3
- <file preprocess="xml-stripblanks">gr-big-cuisine-tile.ui</file>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+ /* gr-recipe-exporter.c:
+ *
+ * Copyright (C) 2016 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 3
+ <file preprocess="xml-stripblanks">gr-big-cuisine-tile.ui</file>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
#include "config.h"
@@ -83,7 +83,8 @@ static guint done_signal;
static void
gr_recipe_exporter_class_init (GrRecipeExporterClass *klass)
-{
+{
+ g_print("gr_recipe_exporter_class_init\n");
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gr_recipe_exporter_finalize;
@@ -100,11 +101,13 @@ gr_recipe_exporter_class_init (GrRecipeExporterClass *klass)
static void
gr_recipe_exporter_init (GrRecipeExporter *self)
{
+ g_print("gr_recipe_exporter_init\n");
}
GrRecipeExporter *
gr_recipe_exporter_new (GtkWindow *parent)
-{
+{
+ g_print("gr_recipe_exporter_new\n");
GrRecipeExporter *exporter;
exporter = g_object_new (GR_TYPE_RECIPE_EXPORTER, NULL);
@@ -117,6 +120,7 @@ gr_recipe_exporter_new (GtkWindow *parent)
static void
cleanup_export (GrRecipeExporter *exporter)
{
+ g_print("cleanup_export\n");
#ifdef ENABLE_AUTOAR
g_clear_object (&exporter->compressor);
#endif
@@ -139,7 +143,8 @@ static void
file_chooser_response (GtkNativeDialog *self,
int response_id,
GrRecipeExporter *exporter)
-{
+{
+ g_print("file_chooser_response\n");
if (response_id == GTK_RESPONSE_ACCEPT) {
g_autoptr(GFile) file = NULL;
@@ -156,7 +161,8 @@ static void
mail_done (GObject *source,
GAsyncResult *result,
gpointer data)
-{
+{
+ g_print("mail_done\n");
GrRecipeExporter *exporter = data;
g_autoptr(GError) error = NULL;
@@ -185,6 +191,7 @@ static void
completed_cb (AutoarCompressor *compressor,
GrRecipeExporter *exporter)
{
+ g_print("completed_cb\n");
g_autofree char *path = NULL;
const char *address;
const char *subject;
@@ -259,7 +266,7 @@ export_one_recipe (GrRecipeExporter *exporter,
GrRecipe *recipe,
GKeyFile *keyfile,
GError **error)
-{
+{ g_print("export_one_recipe\n");
const char *key;
const char *name;
const char *author;
@@ -381,7 +388,7 @@ export_one_chef (GrRecipeExporter *exporter,
GrChef *chef,
GKeyFile *keyfile,
GError **error)
-{
+{ g_print("export_one_chef\n");
const char *key;
const char *name;
const char *fullname;
@@ -431,7 +438,7 @@ export_one_chef (GrRecipeExporter *exporter,
static gboolean
prepare_export (GrRecipeExporter *exporter,
GError **error)
-{
+{g_print("prepare_export\n");
#ifndef ENABLE_AUTOAR
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("This build does not support exporting"));
diff --git a/src/gr-shopping-page.c b/src/gr-shopping-page.c
index ba3387c..29d554c 100644
--- a/src/gr-shopping-page.c
+++ b/src/gr-shopping-page.c
@@ -18,10 +18,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include <goa/goa.h>
#include "gr-shopping-page.h"
#include "gr-shopping-tile.h"
@@ -34,6 +37,9 @@
#include "gr-shopping-list-printer.h"
#include "gr-shopping-list-formatter.h"
#include "gr-mail.h"
+#include "gr-ingredients-exporter.h"
+
+
struct _GrShoppingPage
@@ -50,6 +56,7 @@ struct _GrShoppingPage
int ingredient_count;
int recipe_count;
GrRecipeSearch *search;
+ GrIngredientsExporter *exporter;
GtkSizeGroup *group;
GHashTable *ingredients;
@@ -618,7 +625,7 @@ clear_list (GrShoppingPage *page)
gr_window_go_back (GR_WINDOW (window));
}
-static GList *
+GList *
get_recipes (GrShoppingPage *page)
{
GList *children, *l, *recipes;
@@ -637,7 +644,7 @@ get_recipes (GrShoppingPage *page)
return recipes;
}
-static GList *
+GList *
get_ingredients (GrShoppingPage *page)
{
GList *children, *l, *ingredients;
@@ -746,9 +753,11 @@ mail_done (GObject *source,
}
}
-static void
-share_list (GrShoppingPage *page)
+void share_list (GrShoppingPage *page)
{
+ // GtkWidget *test = gtk_dialog_new();
+ // gtk_widget_show (test);
+
GList *recipes, *items;
g_autofree char *text = NULL;
GtkWidget *window;
@@ -769,6 +778,19 @@ share_list (GrShoppingPage *page)
}
static void
+open_export_shopping_list_dialog (GrShoppingPage *page)
+{
+ if (!page->exporter) {
+ GtkWidget *window;
+
+ window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
+ page->exporter = gr_ingredients_exporter_new(GTK_WINDOW (window));
+ }
+ gr_ingredients_exporter_export (page->exporter);
+}
+
+
+static void
gr_shopping_page_init (GrShoppingPage *page)
{
gtk_widget_set_has_window (GTK_WIDGET (page), FALSE);
@@ -849,7 +871,7 @@ gr_shopping_page_class_init (GrShoppingPageClass *klass)
gtk_widget_class_bind_template_callback (widget_class, clear_list);
gtk_widget_class_bind_template_callback (widget_class, print_list);
- gtk_widget_class_bind_template_callback (widget_class, share_list);
+ gtk_widget_class_bind_template_callback (widget_class, open_export_shopping_list_dialog);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_callback (widget_class, removed_row_activated);
}
diff --git a/src/gr-shopping-page.h b/src/gr-shopping-page.h
index 6992d63..70afbbd 100644
--- a/src/gr-shopping-page.h
+++ b/src/gr-shopping-page.h
@@ -32,6 +32,9 @@ G_DECLARE_FINAL_TYPE (GrShoppingPage, gr_shopping_page, GR, SHOPPING_PAGE, GtkBo
GtkWidget *gr_shopping_page_new (void);
+GList * get_ingredients (GrShoppingPage *page);
+void share_list (GrShoppingPage *page);
+
void gr_shopping_page_populate (GrShoppingPage *self);
G_END_DECLS
diff --git a/src/gr-shopping-page.ui b/src/gr-shopping-page.ui
index 6f1e5d7..3945a0b 100644
--- a/src/gr-shopping-page.ui
+++ b/src/gr-shopping-page.ui
@@ -141,7 +141,7 @@
<property name="visible">1</property>
<property name="use-underline">1</property>
<property name="label" translatable="yes">_Share</property>
- <signal name="clicked" handler="share_list" swapped="yes"/>
+ <signal name="clicked" handler="open_export_shopping_list_dialog" swapped="yes"/>
</object>
<packing>
<property name="pack-type">end</property>
diff --git a/src/ingredients-exporter-dialog.ui b/src/ingredients-exporter-dialog.ui
new file mode 100644
index 0000000..cb50332
--- /dev/null
+++ b/src/ingredients-exporter-dialog.ui
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="gnome-recipes">
+ <object class="GtkDialog" id="dialog">
+ <property name="use-header-bar">1</property>
+ <property name="modal">1</property>
+ <property name="resizable">0</property>
+ <property name="destroy-with-parent">1</property>
+ <property name="default-width">420</property>
+ <property name="default-height">280</property>
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="header">
+ <property name="visible">1</property>
+ <property name="title" translatable="yes">Export Ingredients</property>
+ <child>
+ <object class="GtkStack" id="header_start_stack">
+ <property name="visible">1</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="visible">1</property>
+ <property name="use-underline">1</property>
+ <property name="label" translatable="yes">Cancel</property>
+ </object>
+ <packing>
+ <property name="name">cancel_button</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="back_button">
+ <property name="visible">1</property>
+ <property name="halign">start</property>
+ <signal name="clicked" handler="go_back" swapped="yes"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">back</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="export_button">
+ <property name="visible">1</property>
+ <property name="use-underline">1</property>
+ <property name="label" translatable="yes">Export</property>
+ <signal name="clicked" handler="show_providers"/>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox">
+ <child>
+ <object class="GtkStack" id="dialog_stack">
+ <property name="visible">1</property>
+ <child>
+ <object class="GtkBox" id="accounts_box">
+ <property name="margin">20</property>
+ <property name="spacing">20</property>
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkListBox" id="accounts_list">
+ <property name="visible">1</property>
+ <property name="selection_mode">single</property>
+ <style>
+ <class name="frame"/>
+ </style>
+ <child>
+ <object class="GtkListBoxRow">
+ <property name="visible">1</property>
+ <property name="can_focus">1</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">1</property>
+ <property name="border_width">6</property>
+ <property name="margin_end">18</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="pixel_size">32</property>
+ <property name="icon_name">mail-unread-symbolic</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">1</property>
+ <property name="label" translatable="yes">Email</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkListBoxRow" id="todoist_account_row">
+ <!-- <property name="visible">1</property> -->
+ <property name="can_focus">1</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">1</property>
+ <property name="border_width">6</property>
+ <property name="margin_end">18</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="pixel_size">32</property>
+ <property name="icon_name">goa-account-todoist</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="todoist_label">
+ <property name="visible">1</property>
+ <property name="label" translatable="yes">Todoist</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="add_service">
+ <property name="label"><a href="">Add service</a></property>
+ <property name="visible">1</property>
+ <property name="use_markup">1</property>
+ <property name="use_underline">0</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">accounts_box</property>
+ </packing >
+ </child>
+ <child>
+ <object class="GtkBox" id="providers_box">
+ <property name="margin">20</property>
+ <property name="spacing">20</property>
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkListBox" id="providers_list">
+ <property name="selection_mode">single</property>
+ <property name="visible">1</property>
+ <signal name="selected-rows-changed" handler="row_changed"/>
+ <style>
+ <class name="frame"/>
+ </style>
+ <child>
+ <object class="GtkListBoxRow" id="todoist_provider_row">
+ <property name="visible">1</property>
+ <property name="can_focus">1</property>
+ <child>
+ <object class="GtkGrid" >
+ <property name="visible">1</property>
+ <property name="border_width">6</property>
+ <property name="margin_end">18</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="pixel_size">32</property>
+ <property name="icon_name">goa-account-todoist</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">1</property>
+ <property name="label" translatable="yes">Todoist</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">providers_box</property>
+ </packing >
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/src/meson.build b/src/meson.build
index 2d8b6f3..521a4ad 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -77,6 +77,7 @@ src += ['main.c',
'gr-image-page.c',
'gr-ingredient.c',
'gr-ingredient-row.c',
+ 'gr-ingredients-exporter.c',
'gr-ingredients-list.c',
'gr-ingredients-viewer.c',
'gr-ingredients-viewer-row.c',
diff --git a/src/recipes.gresource.xml b/src/recipes.gresource.xml
index 2b66091..4c2e52d 100644
--- a/src/recipes.gresource.xml
+++ b/src/recipes.gresource.xml
@@ -29,6 +29,7 @@
<file preprocess="xml-stripblanks">gr-query-editor.ui</file>
<file preprocess="xml-stripblanks">gr-window.ui</file>
<file preprocess="xml-stripblanks">chef-conflict-dialog.ui</file>
+ <file preprocess="xml-stripblanks">ingredients-exporter-dialog.ui</file>
<file preprocess="xml-stripblanks">recipe-conflict-dialog.ui</file>
<file preprocess="xml-stripblanks">recipe-export-dialog.ui</file>
<file preprocess="xml-stripblanks">recipe-whats-new-dialog.ui</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]