[recipes] Handle serves count properly with shopping



commit 545410b04ebe0d0db5ff2ee4ac15803138bcaee5
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Feb 11 09:02:59 2017 -0500

    Handle serves count properly with shopping
    
    Persist the serves count for the recipes on the shopping list,
    and transfer the count from the details page when adding
    recipes to the shopping list.

 src/gr-details-page.c      |    4 ++-
 src/gr-recipe-small-tile.c |   24 +++++++++++-------
 src/gr-recipe-small-tile.h |    4 ++-
 src/gr-recipe-store.c      |   57 ++++++++++++++++++++++++++++++++++++++++----
 src/gr-recipe-store.h      |    5 +++-
 src/gr-shopping-page.c     |   30 ++++++++++++++++++++--
 6 files changed, 104 insertions(+), 20 deletions(-)
---
diff --git a/src/gr-details-page.c b/src/gr-details-page.c
index 16df194..687ed41 100644
--- a/src/gr-details-page.c
+++ b/src/gr-details-page.c
@@ -183,9 +183,11 @@ shop_it (GrDetailsPage *page)
 {
         GrRecipeStore *store;
         GtkWidget *window;
+        int serves;
 
         store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
-        gr_recipe_store_add_to_shopping (store, page->recipe);
+        serves = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (page->serves_spin));
+        gr_recipe_store_add_to_shopping (store, page->recipe, serves);
 
         window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
         gr_window_offer_shopping (GR_WINDOW (window));
diff --git a/src/gr-recipe-small-tile.c b/src/gr-recipe-small-tile.c
index 182a062..6e30989 100644
--- a/src/gr-recipe-small-tile.c
+++ b/src/gr-recipe-small-tile.c
@@ -57,8 +57,8 @@ enum {
 };
 
 static void
-set_serves (GrRecipeSmallTile *tile,
-            int                serves)
+recipe_small_tile_set_serves (GrRecipeSmallTile *tile,
+                              int                serves)
 {
         g_autofree char *tmp = NULL;
 
@@ -109,8 +109,6 @@ recipe_small_tile_set_recipe (GrRecipeSmallTile *tile,
                 tmp = g_strdup_printf (_("by %s"), chef ? gr_chef_get_name (chef) : _("Anonymous"));
                 gtk_label_set_label (GTK_LABEL (tile->author), tmp);
         }
-
-        set_serves (tile, gr_recipe_get_serves (recipe));
 }
 
 static void
@@ -125,7 +123,7 @@ serves_value_changed (GrRecipeSmallTile *tile)
         int serves;
 
         serves = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (tile->serves_spin));
-        set_serves (tile, serves);
+        recipe_small_tile_set_serves (tile, serves);
 }
 
 static void
@@ -153,7 +151,7 @@ gr_recipe_small_tile_init (GrRecipeSmallTile *tile)
 {
         gtk_widget_set_has_window (GTK_WIDGET (tile), FALSE);
         gtk_widget_init_template (GTK_WIDGET (tile));
-        set_serves (tile, 1);
+        recipe_small_tile_set_serves (tile, 1);
 }
 
 static void
@@ -183,7 +181,7 @@ recipe_small_tile_set_property (GObject      *object,
 
         switch (prop_id) {
         case PROP_SERVES:
-                set_serves (self, g_value_get_int (value));
+                recipe_small_tile_set_serves (self, g_value_get_int (value));
                 break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -223,12 +221,14 @@ gr_recipe_small_tile_class_init (GrRecipeSmallTileClass *klass)
 }
 
 GtkWidget *
-gr_recipe_small_tile_new (GrRecipe *recipe)
+gr_recipe_small_tile_new (GrRecipe *recipe,
+                          int       serves)
 {
         GrRecipeSmallTile *tile;
 
         tile = g_object_new (GR_TYPE_RECIPE_SMALL_TILE, NULL);
-        recipe_small_tile_set_recipe (GR_RECIPE_SMALL_TILE (tile), recipe);
+        recipe_small_tile_set_recipe (tile, recipe);
+        recipe_small_tile_set_serves (tile, serves);
 
         return GTK_WIDGET (tile);
 }
@@ -238,3 +238,9 @@ gr_recipe_small_tile_get_recipe (GrRecipeSmallTile *tile)
 {
         return tile->recipe;
 }
+
+int
+gr_recipe_small_tile_get_serves (GrRecipeSmallTile *tile)
+{
+        return tile->serves;
+}
diff --git a/src/gr-recipe-small-tile.h b/src/gr-recipe-small-tile.h
index 38a40ba..59fb82f 100644
--- a/src/gr-recipe-small-tile.h
+++ b/src/gr-recipe-small-tile.h
@@ -30,7 +30,9 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (GrRecipeSmallTile, gr_recipe_small_tile, GR, RECIPE_SMALL_TILE, GtkButton)
 
-GtkWidget      *gr_recipe_small_tile_new        (GrRecipe          *recipe);
+GtkWidget      *gr_recipe_small_tile_new        (GrRecipe          *recipe,
+                                                 int                serves);
 GrRecipe       *gr_recipe_small_tile_get_recipe (GrRecipeSmallTile *tile);
+int             gr_recipe_small_tile_get_serves (GrRecipeSmallTile *tile);
 
 G_END_DECLS
diff --git a/src/gr-recipe-store.c b/src/gr-recipe-store.c
index 66095d1..8b2d20a 100644
--- a/src/gr-recipe-store.c
+++ b/src/gr-recipe-store.c
@@ -45,6 +45,7 @@ struct _GrRecipeStore
         char **picks;
         char **favorites;
         char **shopping;
+        int   *shopping_serves;
         char **featured_chefs;
         char *user;
 
@@ -654,6 +655,7 @@ load_shopping (GrRecipeStore *self,
         g_autoptr(GKeyFile) keyfile = NULL;
         g_autoptr(GError) error = NULL;
         g_autofree char *tmp = NULL;
+        gsize len1, len2;
 
         keyfile = g_key_file_new ();
 
@@ -669,13 +671,24 @@ load_shopping (GrRecipeStore *self,
 
         g_message ("Load shopping db: %s", path);
 
-        self->shopping = g_key_file_get_string_list (keyfile, "Content", "Recipes", NULL, &error);
+        self->shopping = g_key_file_get_string_list (keyfile, "Content", "Recipes", &len1, &error);
         if (error) {
                 if (!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
                         g_warning ("Failed to load shopping: %s", error->message);
                 }
                 g_clear_error (&error);
         }
+        self->shopping_serves = g_key_file_get_integer_list (keyfile, "Content", "Serves", &len2, &error);
+        if (error) {
+                if (!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
+                        g_warning ("Failed to load shopping: %s", error->message);
+                }
+                g_clear_error (&error);
+        }
+
+        if (len1 != len2) {
+                g_warning ("Failed to load shopping: Recipes and Serves lists have different lengths");
+        }
 
         tmp = g_key_file_get_string (keyfile, "Content", "LastChange", &error);
         if (error) {
@@ -704,6 +717,8 @@ save_shopping (GrRecipeStore *self)
 
         g_key_file_set_string_list (keyfile, "Content", "Recipes", (const char * const *)self->shopping, 
g_strv_length (self->shopping));
 
+        g_key_file_set_integer_list (keyfile, "Content", "Serves", self->shopping_serves, g_strv_length 
(self->shopping));
+
         if (self->shopping_change) {
                 g_autofree char *tmp = NULL;
 
@@ -1483,28 +1498,41 @@ gr_recipe_store_last_favorite_change (GrRecipeStore *self)
 
 void
 gr_recipe_store_add_to_shopping (GrRecipeStore *self,
-                                 GrRecipe      *recipe)
+                                 GrRecipe      *recipe,
+                                 int            serves)
 {
         char **strv;
+        int *intv;
         int length;
         int i;
         const char *id;
 
         id = gr_recipe_get_id (recipe);
 
-        if (g_strv_contains ((const char * const*)self->shopping, id))
-                return;
+        for (i = 0; self->shopping[i]; i++) {
+                if (strcmp (self->shopping[i], id) == 0) {
+                        self->shopping_serves[i] = serves;
+                        goto save;
+                }
+        }
 
         length = g_strv_length (self->shopping);
         strv = g_new (char *, length + 2);
         strv[0] = g_strdup (id);
-        for (i = 0; i < length; i++)
+        intv = g_new (int, length + 1);
+        intv[0] = serves;
+        for (i = 0; i < length; i++) {
                 strv[i + 1] = self->shopping[i];
+                intv[i + 1] = self->shopping_serves[i];
+        }
         strv[length + 1] = NULL;
 
         g_free (self->shopping);
+        g_free (self->shopping_serves);
         self->shopping = strv;
+        self->shopping_serves = intv;
 
+save:
         if (self->shopping_change)
                 g_date_time_unref (self->shopping_change);
         self->shopping_change = g_date_time_new_now_utc ();
@@ -1528,6 +1556,7 @@ gr_recipe_store_remove_from_shopping (GrRecipeStore *self,
                         g_free (self->shopping[i]);
                         for (j = i; self->shopping[j]; j++) {
                                 self->shopping[j] = self->shopping[j + 1];
+                                self->shopping_serves[j] = self->shopping_serves[j + 1];
                         }
                         break;
                 }
@@ -1556,6 +1585,24 @@ gr_recipe_store_is_in_shopping (GrRecipeStore *self,
         return g_strv_contains ((const char *const*)self->shopping, id);
 }
 
+int
+gr_recipe_store_get_shopping_serves (GrRecipeStore *self,
+                                     GrRecipe      *recipe)
+{
+        const char *id;
+        int i;
+
+        id = gr_recipe_get_id (recipe);
+
+        for (i = 0; self->shopping[i]; i++) {
+                if (strcmp (self->shopping[i], id) == 0) {
+                        return self->shopping_serves[i];
+                }
+        }
+
+        return 0;
+}
+
 GDateTime *
 gr_recipe_store_last_shopping_change (GrRecipeStore *self)
 {
diff --git a/src/gr-recipe-store.h b/src/gr-recipe-store.h
index f1da9c3..8018974 100644
--- a/src/gr-recipe-store.h
+++ b/src/gr-recipe-store.h
@@ -76,11 +76,14 @@ gboolean        gr_recipe_store_is_favorite         (GrRecipeStore  *self,
                                                      GrRecipe       *recipe);
 GDateTime      *gr_recipe_store_last_favorite_change (GrRecipeStore *self);
 void            gr_recipe_store_add_to_shopping      (GrRecipeStore  *self,
-                                                      GrRecipe       *recipe);
+                                                      GrRecipe       *recipe,
+                                                      int             serves);
 void            gr_recipe_store_remove_from_shopping (GrRecipeStore  *self,
                                                       GrRecipe       *recipe);
 gboolean        gr_recipe_store_is_in_shopping       (GrRecipeStore  *self,
                                                       GrRecipe       *recipe);
+int             gr_recipe_store_get_shopping_serves  (GrRecipeStore  *store,
+                                                      GrRecipe       *recipe);
 GDateTime      *gr_recipe_store_last_shopping_change (GrRecipeStore *self);
 gboolean        gr_recipe_store_has_diet            (GrRecipeStore  *self,
                                                      GrDiets         diet);
diff --git a/src/gr-shopping-page.c b/src/gr-shopping-page.c
index 07cfc3f..40eaa1e 100644
--- a/src/gr-shopping-page.c
+++ b/src/gr-shopping-page.c
@@ -465,7 +465,7 @@ collect_ingredients (GrShoppingPage *page)
                 int serves;
 
                 recipe = gr_recipe_small_tile_get_recipe (GR_RECIPE_SMALL_TILE (tile));
-                g_object_get (tile, "serves", &serves, NULL);
+                serves = gr_recipe_small_tile_get_serves (GR_RECIPE_SMALL_TILE (tile));
                 collect_ingredients_from_recipe (page, recipe, serves);
         }
         g_list_free (children);
@@ -497,6 +497,24 @@ recipes_changed (GrShoppingPage *page)
 }
 
 static void
+serves_changed (GObject *object, GParamSpec *pspec, GrShoppingPage *page)
+{
+        GrRecipeSmallTile *tile = GR_RECIPE_SMALL_TILE (object);
+        GrRecipeStore *store;
+        GrRecipe *recipe;
+        int serves;
+
+        recipe = gr_recipe_small_tile_get_recipe (tile);
+        serves = gr_recipe_small_tile_get_serves (tile);
+
+        store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+
+        gr_recipe_store_add_to_shopping (store, recipe, serves);
+
+        recipes_changed (page);
+}
+
+static void
 search_started (GrRecipeSearch *search,
                 GrShoppingPage     *page)
 {
@@ -509,13 +527,19 @@ search_hits_added (GrRecipeSearch *search,
                    GList          *hits,
                    GrShoppingPage *page)
 {
+        GrRecipeStore *store;
         GList *l;
 
+        store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+
         for (l = hits; l; l = l->next) {
                 GrRecipe *recipe = l->data;
                 GtkWidget *tile;
-                tile = gr_recipe_small_tile_new (recipe);
-                g_signal_connect_swapped (tile, "notify::serves", G_CALLBACK (recipes_changed), page);
+                int serves;
+
+                serves = gr_recipe_store_get_shopping_serves (store, recipe);
+                tile = gr_recipe_small_tile_new (recipe, serves);
+                g_signal_connect (tile, "notify::serves", G_CALLBACK (serves_changed), page);
                 gtk_container_add (GTK_CONTAINER (page->recipe_list), tile);
                 page->recipe_count++;
         }


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