[recipes] Introduce a segmented ingredients list
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Introduce a segmented ingredients list
- Date: Fri, 23 Dec 2016 15:37:46 +0000 (UTC)
commit c127b9420949c0f56b43175e7dbe92fa46a40244
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Dec 20 20:02:14 2016 -0500
Introduce a segmented ingredients list
This makes it possible to have separate ingredient lists
for, say, the dough and the frosting of a cake. There are
multiple small visual fixups to the edit page here too,
following a new mockup by Jakub.
The text format for the ingredients list now looks like this:
amount unit ingredient\tsegment\n
src/gr-details-page.c | 90 ++++++----
src/gr-details-page.ui | 7 +-
src/gr-edit-page.c | 292 +++++++++++++++++++++++++++------
src/gr-edit-page.ui | 397 ++++++++++++++++++++-------------------------
src/gr-ingredients-list.c | 41 ++++-
src/gr-ingredients-list.h | 4 +-
src/gr-recipe-store.c | 13 +-
7 files changed, 519 insertions(+), 325 deletions(-)
---
diff --git a/src/gr-details-page.c b/src/gr-details-page.c
index 04c70c1..1ada851 100644
--- a/src/gr-details-page.c
+++ b/src/gr-details-page.c
@@ -119,7 +119,7 @@ struct _GrDetailsPage
GtkWidget *warning_box;
GtkWidget *spicy_warning;
GtkWidget *garlic_warning;
- GtkWidget *ingredients_list;
+ GtkWidget *ingredients_box;
GtkWidget *instructions_label;
GtkWidget *cooking_revealer;
GtkWidget *ingredients_check;
@@ -588,9 +588,6 @@ gr_details_page_init (GrDetailsPage *page)
NULL,
NULL);
- gtk_list_box_set_header_func (GTK_LIST_BOX (page->ingredients_list),
- all_headers, NULL, NULL);
-
g_signal_connect (gtk_text_view_get_buffer (GTK_TEXT_VIEW (page->notes_field)), "changed",
G_CALLBACK (schedule_save), page);
}
@@ -611,7 +608,7 @@ gr_details_page_class_init (GrDetailsPageClass *klass)
gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, warning_box);
gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, spicy_warning);
gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, garlic_warning);
- gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, ingredients_list);
+ gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, ingredients_box);
gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, instructions_label);
gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, cooking_revealer);
gtk_widget_class_bind_template_child (widget_class, GrDetailsPage, ingredients_check);
@@ -660,43 +657,64 @@ populate_ingredients (GrDetailsPage *page,
int denom)
{
g_autoptr(GtkSizeGroup) group = NULL;
+ g_autofree char **segments = NULL;
g_auto(GStrv) ings = NULL;
- int i;
+ int i, j;
+ GtkWidget *list;
+ GtkWidget *label;
+
+ container_remove_all (GTK_CONTAINER (page->ingredients_box));
group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- container_remove_all (GTK_CONTAINER (page->ingredients_list));
- ings = gr_ingredients_list_get_ingredients (page->ingredients);
- for (i = 0; ings[i]; i++) {
- GtkWidget *row;
- GtkWidget *box;
- GtkWidget *label;
- g_autofree char *s = NULL;
-
- box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show (box);
-
- s = gr_ingredients_list_scale_unit (page->ingredients, ings[i], num, denom);
- label = gtk_label_new (s);
- g_object_set (label,
- "visible", TRUE,
- "xalign", 0.0,
- "margin", 10,
- NULL);
- gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
- gtk_container_add (GTK_CONTAINER (box), label);
- gtk_size_group_add_widget (group, label);
-
- label = gtk_label_new (ings[i]);
- g_object_set (label,
- "visible", TRUE,
- "xalign", 0.0,
+ segments = gr_ingredients_list_get_segments (page->ingredients);
+ for (j = 0; segments[j]; j++) {
+ if (segments[j] && segments[j][0]) {
+ label = gtk_label_new (segments[j]);
+ gtk_widget_show (label);
+ gtk_label_set_xalign (GTK_LABEL (label), 0);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), "heading");
+ gtk_container_add (GTK_CONTAINER (page->ingredients_box), label);
+ }
+
+ list = gtk_list_box_new ();
+ gtk_widget_show (list);
+ gtk_style_context_add_class (gtk_widget_get_style_context (list), "frame");
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
+ gtk_list_box_set_header_func (GTK_LIST_BOX (list), all_headers, NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (page->ingredients_box), list);
+
+ ings = gr_ingredients_list_get_ingredients (page->ingredients, segments[j]);
+ for (i = 0; ings[i]; i++) {
+ GtkWidget *row;
+ GtkWidget *box;
+ g_autofree char *s = NULL;
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_show (box);
+
+ s = gr_ingredients_list_scale_unit (page->ingredients, ings[i], num, denom);
+ label = gtk_label_new (s);
+ g_object_set (label,
+ "visible", TRUE,
+ "xalign", 0.0,
+ "margin", 10,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+ gtk_container_add (GTK_CONTAINER (box), label);
+ gtk_size_group_add_widget (group, label);
+
+ label = gtk_label_new (ings[i]);
+ g_object_set (label,
+ "visible", TRUE,
+ "xalign", 0.0,
"margin", 10,
NULL);
- gtk_container_add (GTK_CONTAINER (box), label);
+ gtk_container_add (GTK_CONTAINER (box), label);
- gtk_container_add (GTK_CONTAINER (page->ingredients_list), box);
- row = gtk_widget_get_parent (box);
- gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+ gtk_container_add (GTK_CONTAINER (list), box);
+ row = gtk_widget_get_parent (box);
+ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), FALSE);
+ }
}
gtk_widget_hide (page->warning_box);
diff --git a/src/gr-details-page.ui b/src/gr-details-page.ui
index 5a7c63f..2fe0f4b 100644
--- a/src/gr-details-page.ui
+++ b/src/gr-details-page.ui
@@ -154,12 +154,9 @@ followed</property>
</object>
</child>
<child>
- <object class="GtkListBox" id="ingredients_list">
+ <object class="GtkBox" id="ingredients_box">
<property name="visible">1</property>
- <property name="selection-mode">none</property>
- <style>
- <class name="frame"/>
- </style>
+ <property name="orientation">vertical</property>
</object>
</child>
</object>
diff --git a/src/gr-edit-page.c b/src/gr-edit-page.c
index 999c79b..1d219ca 100644
--- a/src/gr-edit-page.c
+++ b/src/gr-edit-page.c
@@ -60,7 +60,7 @@ struct _GrEditPage
GtkWidget *spiciness_combo;
GtkWidget *prep_time_combo;
GtkWidget *cook_time_combo;
- GtkWidget *ingredients_list;
+ GtkWidget *description_field;
GtkWidget *instructions_field;
GtkWidget *serves_spin;
GtkWidget *gluten_free_check;
@@ -78,12 +78,14 @@ struct _GrEditPage
GtkWidget *new_ingredient_amount;
GtkWidget *new_ingredient_unit;
GtkWidget *new_ingredient_add_button;
- GtkWidget *remove_ingredient_button;
GtkWidget *author_label;
+ GtkWidget *ingredients_box;
GtkSizeGroup *group;
guint account_response_signal_id;
+
+ GList *segments;
};
G_DEFINE_TYPE (GrEditPage, gr_edit_page, GTK_TYPE_BOX)
@@ -139,6 +141,7 @@ edit_page_finalize (GObject *object)
g_clear_object (&self->recipe);
g_clear_object (&self->group);
+ g_list_free (self->segments);
G_OBJECT_CLASS (gr_edit_page_parent_class)->finalize (object);
}
@@ -191,14 +194,17 @@ populate_season_combo (GrEditPage *page)
}
static void
-add_ingredient (GrEditPage *page)
+add_ingredient (GtkButton *button, GrEditPage *page)
{
+ gtk_popover_set_relative_to (GTK_POPOVER (page->ingredient_popover),
+ GTK_WIDGET (button));
gtk_popover_popup (GTK_POPOVER (page->ingredient_popover));
}
static void
remove_ingredient (GrEditPage *page)
{
+#if 0
GtkListBoxRow *row;
row = gtk_list_box_get_selected_row (GTK_LIST_BOX (page->ingredients_list));
@@ -206,22 +212,19 @@ remove_ingredient (GrEditPage *page)
return;
gtk_container_remove (GTK_CONTAINER (page->ingredients_list), GTK_WIDGET (row));
-
+#endif
}
static void
selected_rows_changed (GrEditPage *page)
{
- GtkListBoxRow *row;
-
- row = gtk_list_box_get_selected_row (GTK_LIST_BOX (page->ingredients_list));
- gtk_widget_set_sensitive (page->remove_ingredient_button, row != NULL);
}
static void
-add_ingredient_row (GrEditPage *page,
- const char *unit,
- const char *ingredient)
+add_ingredient_row (GtkWidget *list,
+ GtkSizeGroup *group,
+ const char *unit,
+ const char *ingredient)
{
GtkWidget *box;
GtkWidget *label;
@@ -238,7 +241,7 @@ add_ingredient_row (GrEditPage *page,
NULL);
gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
gtk_container_add (GTK_CONTAINER (box), label);
- gtk_size_group_add_widget (page->group, label);
+ gtk_size_group_add_widget (group, label);
label = gtk_label_new (ingredient);
g_object_set (label,
@@ -248,7 +251,7 @@ add_ingredient_row (GrEditPage *page,
NULL);
gtk_container_add (GTK_CONTAINER (box), label);
- gtk_container_add (GTK_CONTAINER (page->ingredients_list), box);
+ gtk_container_add (GTK_CONTAINER (list), box);
row = gtk_widget_get_parent (box);
g_object_set_data_full (G_OBJECT (row), "ingredient", g_strdup_printf ("%s %s", unit, ingredient),
g_free);
@@ -256,38 +259,55 @@ add_ingredient_row (GrEditPage *page,
}
static void
-add_ingredient2 (GrEditPage *page)
+add_ingredient2 (GtkButton *button, GrEditPage *page)
{
const char *ingredient;
double amount;
const char *unit;
g_autofree char *s = NULL;
+ GtkWidget *list;
+ GtkWidget *b;
gtk_popover_popdown (GTK_POPOVER (page->ingredient_popover));
+ b = gtk_popover_get_relative_to (GTK_POPOVER (page->ingredient_popover));
+ list = GTK_WIDGET (g_object_get_data (G_OBJECT (b), "list"));
+
ingredient = gtk_entry_get_text (GTK_ENTRY (page->new_ingredient_name));
amount = gtk_spin_button_get_value (GTK_SPIN_BUTTON (page->new_ingredient_amount));
unit = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (page->new_ingredient_unit))));
s = g_strdup_printf ("%g %s", amount, unit);
- add_ingredient_row (page, s, ingredient);
+ add_ingredient_row (list, page->group, s, ingredient);
}
static char *
collect_ingredients (GrEditPage *page)
{
GString *s;
- GList *children, *l;
+ GtkWidget *segment;
+ GtkWidget *list;
+ GtkWidget *entry;
+ GList *children, *l, *k;
s = g_string_new ("");
- children = gtk_container_get_children (GTK_CONTAINER (page->ingredients_list));
- for (l = children; l; l = l->next) {
- GtkWidget *row = l->data;
- if (s->len > 0)
- g_string_append (s, "\n");
- g_string_append (s, (const char *)g_object_get_data (G_OBJECT (row), "ingredient"));
+ for (k = page->segments; k; k = k->next) {
+ segment = k->data;
+ list = GTK_WIDGET (g_object_get_data (G_OBJECT (segment), "list"));
+ entry = GTK_WIDGET (g_object_get_data (G_OBJECT (segment), "entry"));
+ children = gtk_container_get_children (GTK_CONTAINER (list));
+ for (l = children; l; l = l->next) {
+ GtkWidget *row = l->data;
+ if (s->len > 0)
+ g_string_append (s, "\n");
+ g_string_append (s, (const char *)g_object_get_data (G_OBJECT (row), "ingredient"));
+ if (page->segments->next != NULL) {
+ g_string_append (s, "\t");
+ g_string_append (s, gtk_entry_get_text (GTK_ENTRY (entry)));
+ }
+ }
+ g_list_free (children);
}
- g_list_free (children);
return g_string_free (s, FALSE);
}
@@ -315,9 +335,6 @@ gr_edit_page_init (GrEditPage *page)
page->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- gtk_list_box_set_header_func (GTK_LIST_BOX (page->ingredients_list),
- all_headers, NULL, NULL);
-
populate_cuisine_combo (page);
populate_category_combo (page);
populate_season_combo (page);
@@ -344,7 +361,7 @@ gr_edit_page_class_init (GrEditPageClass *klass)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, cook_time_combo);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, serves_spin);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, spiciness_combo);
- gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, ingredients_list);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, description_field);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, instructions_field);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, gluten_free_check);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, nut_free_check);
@@ -360,8 +377,8 @@ gr_edit_page_class_init (GrEditPageClass *klass)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, new_ingredient_name);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, new_ingredient_amount);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, new_ingredient_unit);
- gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage,
remove_ingredient_button);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, author_label);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, ingredients_box);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), dismiss_error);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), add_image);
@@ -369,7 +386,6 @@ gr_edit_page_class_init (GrEditPageClass *klass)
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), rotate_image_left);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), rotate_image_right);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), images_changed);
- gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), add_ingredient);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), add_ingredient2);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), remove_ingredient);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), selected_rows_changed);
@@ -464,6 +480,191 @@ get_spiciness (GrEditPage *page)
return 90;
}
+static void add_list (GtkButton *button, GrEditPage *page);
+static void remove_list (GtkButton *button, GrEditPage *page);
+static void update_segments (GrEditPage *page);
+
+static GtkWidget *
+add_ingredients_segment (GrEditPage *page,
+ const char *segment_label)
+{
+ GtkWidget *segment;
+ GtkWidget *label;
+ GtkWidget *entry;
+ GtkWidget *list;
+ GtkWidget *box;
+ GtkWidget *button;
+ GtkWidget *stack;
+ GtkWidget *image;
+
+ segment = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ g_object_set (segment,
+ "margin-top", 20,
+ "margin-bottom", 20,
+ NULL);
+ gtk_widget_show (segment);
+ gtk_container_add (GTK_CONTAINER (page->ingredients_box), segment);
+
+ stack = gtk_stack_new ();
+ g_object_set_data (G_OBJECT (segment), "stack", stack);
+ gtk_widget_show (stack);
+ gtk_container_add (GTK_CONTAINER (segment), stack);
+
+ label = g_object_new (GTK_TYPE_LABEL,
+ "label", segment_label[0] ? segment_label : _("Ingredients"),
+ "xalign", 0.0,
+ "visible", TRUE,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), "heading");
+ gtk_stack_add_named (GTK_STACK (stack), label, "label");
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_widget_set_valign (box, GTK_ALIGN_START);
+ gtk_widget_show (box);
+
+ entry = gtk_entry_new ();
+ g_object_set_data (G_OBJECT (segment), "entry", entry);
+ gtk_widget_set_halign (box, GTK_ALIGN_FILL);
+ gtk_widget_show (entry);
+ gtk_entry_set_text (GTK_ENTRY (entry), segment_label[0] ? segment_label : _("Ingredients for …"));
+
+ gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
+
+ button = gtk_button_new_with_label (_("Remove"));
+ g_object_set_data (G_OBJECT (button), "segment", segment);
+ g_object_set_data (G_OBJECT (segment), "remove-list", button);
+ g_signal_connect (button, "clicked", G_CALLBACK (remove_list), page);
+ gtk_widget_show (button);
+ gtk_container_add (GTK_CONTAINER (box), button);
+
+ gtk_stack_add_named (GTK_STACK (stack), box, "entry");
+
+ list = gtk_list_box_new ();
+ g_object_set_data (G_OBJECT (segment), "list", list);
+
+ gtk_widget_show (list);
+ gtk_style_context_add_class (gtk_widget_get_style_context (list), "frame");
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), GTK_SELECTION_NONE);
+ gtk_list_box_set_header_func (GTK_LIST_BOX (list), all_headers, NULL, NULL);
+
+ label = g_object_new (GTK_TYPE_LABEL,
+ "label", _("No ingredients added yet"),
+ "xalign", 0.5,
+ "halign", GTK_ALIGN_FILL,
+ "margin-start", 20,
+ "margin-end", 20,
+ "margin-top", 10,
+ "margin-bottom", 10,
+ "visible", TRUE,
+ NULL);
+ gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
+ gtk_list_box_set_placeholder (GTK_LIST_BOX (list), label);
+
+ gtk_container_add (GTK_CONTAINER (segment), list);
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_widget_set_halign (box, GTK_ALIGN_START);
+ gtk_widget_show (box);
+
+ button = gtk_button_new ();
+ gtk_widget_set_tooltip_text (button, _("Add Ingredient"));
+ image = gtk_image_new_from_icon_name ("list-add-symbolic", 1);
+ gtk_widget_show (image);
+ gtk_widget_set_margin_top (button, 10);
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_style_context_add_class (gtk_widget_get_style_context (button), "dim-label");
+ gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button");
+ gtk_style_context_remove_class (gtk_widget_get_style_context (button), "text-button");
+ g_signal_connect (button, "clicked", G_CALLBACK (add_ingredient), page);
+ gtk_widget_show (button);
+ gtk_container_add (GTK_CONTAINER (box), button);
+ g_object_set_data (G_OBJECT (button), "list", list);
+
+ gtk_container_add (GTK_CONTAINER (segment), box);
+
+ page->segments = g_list_append (page->segments, segment);
+
+ return list;
+}
+
+static void
+add_list (GtkButton *button, GrEditPage *page)
+{
+ add_ingredients_segment (page, "");
+
+ update_segments (page);
+}
+
+static void
+remove_list (GtkButton *button, GrEditPage *page)
+{
+ GtkWidget *segment;
+
+ segment = GTK_WIDGET (g_object_get_data (G_OBJECT (button), "segment"));
+
+ page->segments = g_list_remove (page->segments, segment);
+ gtk_widget_destroy (segment);
+
+ update_segments (page);
+}
+
+static void
+update_segments (GrEditPage *page)
+{
+ GList *l;
+ GtkWidget *segment;
+ GtkWidget *stack;
+ GtkWidget *button;
+
+ for (l = page->segments; l; l = l->next) {
+ segment = l->data;
+ stack = GTK_WIDGET (g_object_get_data (G_OBJECT (segment), "stack"));
+ button = GTK_WIDGET (g_object_get_data (G_OBJECT (segment), "remove-list"));
+ if (page->segments->next == NULL)
+ gtk_stack_set_visible_child_name (GTK_STACK (stack), "label");
+ else {
+ gtk_stack_set_visible_child_name (GTK_STACK (stack), "entry");
+ gtk_widget_set_visible (button, l != page->segments);
+ }
+ }
+}
+
+static void
+populate_ingredients (GrEditPage *page,
+ const char *text)
+{
+ g_autoptr(GrIngredientsList) ingredients = NULL;
+ g_autofree char **segs = NULL;
+ g_auto(GStrv) ings = NULL;
+ int i, j;
+ GtkWidget *list;
+ GtkWidget *button;
+
+ container_remove_all (GTK_CONTAINER (page->ingredients_box));
+ g_list_free (page->segments);
+ page->segments = NULL;
+
+ ingredients = gr_ingredients_list_new (text);
+ segs = gr_ingredients_list_get_segments (ingredients);
+ for (j = 0; segs[j]; j++) {
+ list = add_ingredients_segment (page, segs[j]);
+ ings = gr_ingredients_list_get_ingredients (ingredients, segs[j]);
+ for (i = 0; ings[i]; i++) {
+ g_autofree char *s = NULL;
+ s = gr_ingredients_list_scale_unit (ingredients, ings[i], 1, 1);
+ add_ingredient_row (list, page->group, s, ings[i]);
+ }
+ }
+
+ button = gtk_button_new_with_label (_("Add List"));
+ gtk_widget_show (button);
+ gtk_widget_set_halign (button, GTK_ALIGN_FILL);
+ gtk_box_pack_end (GTK_BOX (page->ingredients_box), button, FALSE, TRUE, 0);
+ g_signal_connect (button, "clicked", G_CALLBACK (add_list), page);
+
+ update_segments (page);
+}
+
void
gr_edit_page_clear (GrEditPage *page)
{
@@ -478,7 +679,8 @@ gr_edit_page_clear (GrEditPage *page)
set_combo_value (GTK_COMBO_BOX (page->cook_time_combo), "");
gtk_spin_button_set_value (GTK_SPIN_BUTTON (page->serves_spin), 1);
set_spiciness (page, 0);
- container_remove_all (GTK_CONTAINER (page->ingredients_list));
+ populate_ingredients (page, "");
+ set_text_view_text (GTK_TEXT_VIEW (page->description_field), "");
set_text_view_text (GTK_TEXT_VIEW (page->instructions_field), "");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->gluten_free_check), FALSE);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->nut_free_check), FALSE);
@@ -494,25 +696,6 @@ gr_edit_page_clear (GrEditPage *page)
g_clear_object (&page->recipe);
}
-static void
-populate_ingredients (GrEditPage *page,
- GrRecipe *recipe)
-{
- g_autoptr(GrIngredientsList) ingredients = NULL;
- g_auto(GStrv) ings = NULL;
- int i;
-
- container_remove_all (GTK_CONTAINER (page->ingredients_list));
-
- ingredients = gr_ingredients_list_new (gr_recipe_get_ingredients (recipe));
- ings = gr_ingredients_list_get_ingredients (ingredients);
- for (i = 0; ings[i]; i++) {
- g_autofree char *s = NULL;
- s = gr_ingredients_list_scale_unit (ingredients, ings[i], 1, 1);
- add_ingredient_row (page, s, ings[i]);
- }
-}
-
void
gr_edit_page_edit (GrEditPage *page,
GrRecipe *recipe)
@@ -526,7 +709,9 @@ gr_edit_page_edit (GrEditPage *page,
const char *author;
int serves;
int spiciness;
+ const char *description;
const char *instructions;
+ const char *ingredients;
g_autofree char *image_path = NULL;
g_autoptr(GdkPixbuf) pixbuf = NULL;
GrDiets diets;
@@ -545,7 +730,9 @@ gr_edit_page_edit (GrEditPage *page,
prep_time = gr_recipe_get_prep_time (recipe);
cook_time = gr_recipe_get_cook_time (recipe);
diets = gr_recipe_get_diets (recipe);
+ description = gr_recipe_get_description (recipe);
instructions = gr_recipe_get_instructions (recipe);
+ ingredients = gr_recipe_get_ingredients (recipe);
author = gr_recipe_get_author (recipe);
g_object_get (recipe, "images", &images, NULL);
@@ -562,9 +749,10 @@ gr_edit_page_edit (GrEditPage *page,
set_combo_value (GTK_COMBO_BOX (page->cook_time_combo), cook_time);
set_spiciness (page, spiciness);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (page->serves_spin), serves);
+ set_text_view_text (GTK_TEXT_VIEW (page->description_field), description);
set_text_view_text (GTK_TEXT_VIEW (page->instructions_field), instructions);
- populate_ingredients (page, recipe);
+ populate_ingredients (page, ingredients);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->gluten_free_check), (diets &
GR_DIET_GLUTEN_FREE) != 0);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (page->nut_free_check), (diets & GR_DIET_NUT_FREE)
!= 0);
@@ -821,6 +1009,7 @@ gr_edit_page_save (GrEditPage *page)
g_autofree char *cook_time = NULL;
int serves;
int spiciness;
+ g_autofree char *description = NULL;
g_autofree char *ingredients = NULL;
g_autofree char *instructions = NULL;
GrRecipeStore *store;
@@ -840,6 +1029,7 @@ gr_edit_page_save (GrEditPage *page)
spiciness = get_spiciness (page);
serves = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (page->serves_spin));
ingredients = collect_ingredients (page);
+ description = get_text_view_text (GTK_TEXT_VIEW (page->description_field));
instructions = get_text_view_text (GTK_TEXT_VIEW (page->instructions_field));
diets = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->gluten_free_check)) ?
GR_DIET_GLUTEN_FREE : 0) |
(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (page->nut_free_check)) ? GR_DIET_NUT_FREE
: 0) |
@@ -867,6 +1057,7 @@ gr_edit_page_save (GrEditPage *page)
"cook-time", cook_time,
"serves", serves,
"spiciness", spiciness,
+ "description", description,
"ingredients", ingredients,
"instructions", instructions,
"diets", diets,
@@ -893,6 +1084,7 @@ gr_edit_page_save (GrEditPage *page)
"cook-time", cook_time,
"serves", serves,
"spiciness", spiciness,
+ "description", description,
"ingredients", ingredients,
"instructions", instructions,
"diets", diets,
diff --git a/src/gr-edit-page.ui b/src/gr-edit-page.ui
index 99f93a0..3dfd6c4 100644
--- a/src/gr-edit-page.ui
+++ b/src/gr-edit-page.ui
@@ -80,7 +80,6 @@
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
- <property name="spacing">20</property>
<property name="margin-top">20</property>
<property name="valign">start</property>
<property name="halign">end</property>
@@ -100,6 +99,7 @@
<object class="GtkBox">
<property name="visible">1</property>
<property name="halign">start</property>
+ <property name="margin-top">10</property>
<style>
<class name="linked"/>
</style>
@@ -121,7 +121,7 @@
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">list-add-symbolic</property>
- <property name="pixel-size">20</property>
+ <property name="icon-size">1</property>
</object>
</child>
</object>
@@ -147,7 +147,7 @@
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">object-rotate-left-symbolic</property>
- <property name="pixel-size">20</property>
+ <property name="icon-size">1</property>
</object>
</child>
</object>
@@ -173,7 +173,7 @@
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">object-rotate-right-symbolic</property>
- <property name="pixel-size">20</property>
+ <property name="icon-size">1</property>
</object>
</child>
</object>
@@ -199,7 +199,7 @@
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">user-trash-symbolic</property>
- <property name="pixel-size">20</property>
+ <property name="icon-size">1</property>
</object>
</child>
</object>
@@ -213,120 +213,19 @@
</packing>
</child>
<child>
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Ingredients</property>
- <property name="xalign">0</property>
- <style> <class name="heading"/> </style>
- </object>
- </child>
- <child>
- <object class="GtkScrolledWindow">
+ <object class="GtkBox" id="ingredients_box">
<property name="visible">1</property>
- <property name="shadow-type">none</property>
- <property name="hscrollbar-policy">never</property>
- <property name="vscrollbar-policy">never</property>
- <child>
- <object class="GtkListBox" id="ingredients_list">
- <property name="visible">1</property>
- <property name="selection-mode">single</property>
- <signal name="selected-rows-changed" handler="selected_rows_changed"
swapped="yes"/>
- <style>
- <class name="frame"/>
- </style>
- <accessibility>
- <relation target="add_ingredient_button" type="controlled-by"/>
- <relation target="remove_ingredient_button" type="controlled-by"/>
- </accessibility>
- <child type="placeholder">
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="margin-start">20</property>
- <property name="margin-end">20</property>
- <property name="margin-top">10</property>
- <property name="margin-bottom">10</property>
- <property name="halign">fill</property>
- <property name="xalign">0.5</property>
- <property name="label" translatable="yes">No ingredients added yet</property>
- <style> <class name="dim-label"/> </style>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">1</property>
- <property name="spacing">10</property>
- <property name="halign">start</property>
- <child>
- <object class="GtkButton" id="add_ingredient_button">
- <property name="visible">1</property>
- <property name="halign">center</property>
- <property name="valign">start</property>
- <property name="tooltip-text" translatable="yes">Add an ingredient</property>
- <accessibility>
- <relation target="ingredients_list" type="controller-for"/>
- </accessibility>
- <style>
- <class name="image-button"/>
- <class name="circular"/>
- <class name="dim-label"/>
- </style>
- <signal name="clicked" handler="add_ingredient" swapped="yes"/>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">list-add-symbolic</property>
- <property name="pixel-size">20</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="remove_ingredient_button">
- <property name="visible">1</property>
- <property name="halign">center</property>
- <property name="valign">start</property>
- <property name="sensitive">0</property>
- <property name="tooltip-text" translatable="yes">Remove an ingredient</property>
- <accessibility>
- <relation target="ingredients_list" type="controller-for"/>
- </accessibility>
- <style>
- <class name="image-button"/>
- <class name="circular"/>
- <class name="dim-label"/>
- </style>
- <signal name="clicked" handler="remove_ingredient" swapped="yes"/>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">edit-delete-symbolic</property>
- <property name="pixel-size">20</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">1</property>
- </packing>
- </child>
+ <property name="orientation">vertical</property>
</object>
- <packing>
- <property name="fill">1</property>
- </packing>
</child>
<child>
<object class="GtkFlowBox">
<property name="visible">1</property>
+ <property name="margin-top">40</property>
<property name="selection-mode">none</property>
- <property name="min-children-per-line">4</property>
- <property name="max-children-per-line">4</property>
+ <property name="min-children-per-line">3</property>
+ <property name="max-children-per-line">3</property>
<child>
<object class="GtkCheckButton" id="gluten_free_check">
<property name="visible">1</property>
@@ -359,41 +258,36 @@
</child>
</object>
</child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">1</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="column-spacing">20</property>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
- <property name="label" translatable="yes">Other Information</property>
+ <property name="label" translatable="yes">Details</property>
<property name="xalign">0</property>
<style> <class name="heading"/> </style>
</object>
- </child>
- <child>
- <object class="GtkGrid">
- <property name="visible">1</property>
- <property name="row-spacing">20</property>
- <property name="column-spacing">40</property>
- <property name="halign">fill</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="use-underline">1</property>
- <property name="mnemonic-widget">cuisine_combo</property>
- <property name="label" translatable="yes">_Cuisine</property>
- <property name="xalign">1</property>
- <style> <class name="dim-label"/> </style>
- </object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
- <object class="GtkLabel">
+ <object class="GtkLabel" id="name_label">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">category_combo</property>
- <property name="label" translatable="yes">_Meal</property>
+ <property name="mnemonic-widget">name_entry</property>
+ <property name="label" translatable="yes">_Name your recipe</property>
<property name="xalign">1</property>
+ <property name="halign">fill</property>
+ <property name="valign">baseline</property>
<style> <class name="dim-label"/> </style>
</object>
<packing>
@@ -402,19 +296,11 @@
</packing>
</child>
<child>
- <object class="GtkComboBoxText" id="cuisine_combo">
- <property name="visible">1</property>
- <property name="has-entry">1</property>
- </object>
- <packing>
- <property name="left-attach">1</property>
- <property name="top-attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkComboBoxText" id="category_combo">
+ <object class="GtkEntry" id="name_entry">
<property name="visible">1</property>
- <property name="has-entry">1</property>
+ <property name="hexpand">1</property>
+ <property name="valign">baseline</property>
+ <property name="margin-bottom">10</property>
</object>
<packing>
<property name="left-attach">1</property>
@@ -425,8 +311,9 @@
<object class="GtkLabel">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">season_combo</property>
- <property name="label" translatable="yes">S_eason</property>
+ <property name="mnemonic-widget">serves_spin</property>
+ <property name="label" translatable="yes">Ser_ves</property>
+ <property name="valign">baseline</property>
<property name="xalign">1</property>
<style> <class name="dim-label"/> </style>
</object>
@@ -436,12 +323,27 @@
</packing>
</child>
<child>
+ <object class="GtkSpinButton" id="serves_spin">
+ <property name="visible">1</property>
+ <property name="adjustment">serves_adjustment</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="margin-bottom">10</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">spiciness_combo</property>
- <property name="label" translatable="yes">S_piciness</property>
+ <property name="mnemonic-widget">prep_time_combo</property>
+ <property name="label" translatable="yes">_Preparation time</property>
<property name="xalign">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
<style> <class name="dim-label"/> </style>
</object>
<packing>
@@ -450,166 +352,216 @@
</packing>
</child>
<child>
- <object class="GtkComboBoxText" id="season_combo">
+ <object class="GtkComboBoxText" id="prep_time_combo">
<property name="visible">1</property>
<property name="has-entry">1</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
+ <items>
+ <item translatable="yes" id="Less than 15 minutes">Less than 15 minutes</item>
+ <item translatable="yes" id="15 to 30 minutes">15 to 30 minutes</item>
+ <item translatable="yes" id="30 to 45 minutes">30 to 45 minutes</item>
+ <item translatable="yes" id="45 minutes to an hour">45 minutes to an hour</item>
+ <item translatable="yes" id="More than an hour">More than an hour</item>
+ </items>
</object>
<packing>
<property name="left-attach">1</property>
- <property name="top-attach">2</property>
+ <property name="top-attach">3</property>
</packing>
</child>
<child>
- <object class="GtkComboBoxText" id="spiciness_combo">
+ <object class="GtkLabel">
<property name="visible">1</property>
- <items>
- <item translatable="yes" id="mild">Mild</item>
- <item translatable="yes" id="spicy">Somewhat spicy</item>
- <item translatable="yes" id="hot">Hot</item>
- <item translatable="yes" id="extreme">Very spicy</item>
- </items>
+ <property name="use-underline">1</property>
+ <property name="mnemonic-widget">cook_time_combo</property>
+ <property name="label" translatable="yes">C_ooking time</property>
+ <property name="xalign">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">20</property>
+ <style> <class name="dim-label"/> </style>
</object>
<packing>
- <property name="left-attach">1</property>
- <property name="top-attach">3</property>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
</packing>
</child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkGrid">
- <property name="visible">1</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="row-spacing">20</property>
- <property name="column-spacing">40</property>
<child>
- <object class="GtkLabel">
+ <object class="GtkComboBoxText" id="cook_time_combo">
<property name="visible">1</property>
- <property name="label" translatable="yes">Details</property>
- <property name="xalign">0</property>
- <style> <class name="heading"/> </style>
+ <property name="has-entry">1</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">20</property>
+ <items>
+ <item translatable="yes" id="Less than 15 minutes">Less than 15 minutes</item>
+ <item translatable="yes" id="15 to 30 minutes">15 to 30 minutes</item>
+ <item translatable="yes" id="30 to 45 minutes">30 to 45 minutes</item>
+ <item translatable="yes" id="45 minutes to an hour">45 minutes to an hour</item>
+ <item translatable="yes" id="More than an hour">More than an hour</item>
+ </items>
</object>
<packing>
- <property name="left-attach">0</property>
- <property name="top-attach">0</property>
- <property name="width">2</property>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
</packing>
</child>
+
<child>
- <object class="GtkLabel" id="name_label">
+ <object class="GtkLabel">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">name_entry</property>
- <property name="label" translatable="yes">_Name your recipe</property>
+ <property name="mnemonic-widget">cuisine_combo</property>
+ <property name="label" translatable="yes">_Cuisine</property>
<property name="xalign">1</property>
- <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
<style> <class name="dim-label"/> </style>
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">1</property>
+ <property name="top-attach">5</property>
</packing>
</child>
<child>
- <object class="GtkEntry" id="name_entry">
+ <object class="GtkComboBoxText" id="cuisine_combo">
<property name="visible">1</property>
- <property name="hexpand">1</property>
+ <property name="has-entry">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
</object>
<packing>
<property name="left-attach">1</property>
- <property name="top-attach">1</property>
+ <property name="top-attach">5</property>
</packing>
</child>
+
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">serves_spin</property>
- <property name="label" translatable="yes">Ser_ves</property>
+ <property name="mnemonic-widget">category_combo</property>
+ <property name="label" translatable="yes">_Meal</property>
<property name="xalign">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
<style> <class name="dim-label"/> </style>
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">2</property>
+ <property name="top-attach">6</property>
</packing>
</child>
<child>
- <object class="GtkSpinButton" id="serves_spin">
+ <object class="GtkComboBoxText" id="category_combo">
<property name="visible">1</property>
- <property name="adjustment">serves_adjustment</property>
- <property name="halign">start</property>
+ <property name="has-entry">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
</object>
<packing>
<property name="left-attach">1</property>
- <property name="top-attach">2</property>
+ <property name="top-attach">6</property>
</packing>
</child>
+
<child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">prep_time_combo</property>
- <property name="label" translatable="yes">_Preparation time</property>
+ <property name="mnemonic-widget">season_combo</property>
+ <property name="label" translatable="yes">S_eason</property>
<property name="xalign">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
<style> <class name="dim-label"/> </style>
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">3</property>
+ <property name="top-attach">7</property>
</packing>
</child>
<child>
+ <object class="GtkComboBoxText" id="season_combo">
+ <property name="visible">1</property>
+ <property name="has-entry">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">10</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+
+ <child>
<object class="GtkLabel">
<property name="visible">1</property>
<property name="use-underline">1</property>
- <property name="mnemonic-widget">cook_time_combo</property>
- <property name="label" translatable="yes">C_ooking time</property>
+ <property name="mnemonic-widget">spiciness_combo</property>
+ <property name="label" translatable="yes">S_piciness</property>
<property name="xalign">1</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">20</property>
<style> <class name="dim-label"/> </style>
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">4</property>
+ <property name="top-attach">8</property>
</packing>
</child>
<child>
- <object class="GtkComboBoxText" id="prep_time_combo">
+ <object class="GtkComboBoxText" id="spiciness_combo">
<property name="visible">1</property>
- <property name="has-entry">1</property>
- <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="margin-bottom">20</property>
<items>
- <item translatable="yes" id="Less than 15 minutes">Less than 15 minutes</item>
- <item translatable="yes" id="15 to 30 minutes">15 to 30 minutes</item>
- <item translatable="yes" id="30 to 45 minutes">30 to 45 minutes</item>
- <item translatable="yes" id="45 minutes to an hour">45 minutes to an hour</item>
- <item translatable="yes" id="More than an hour">More than an hour</item>
+ <item translatable="yes" id="mild">Mild</item>
+ <item translatable="yes" id="spicy">Somewhat spicy</item>
+ <item translatable="yes" id="hot">Hot</item>
+ <item translatable="yes" id="extreme">Very spicy</item>
</items>
</object>
<packing>
<property name="left-attach">1</property>
- <property name="top-attach">3</property>
+ <property name="top-attach">8</property>
</packing>
</child>
+
<child>
- <object class="GtkComboBoxText" id="cook_time_combo">
+ <object class="GtkLabel">
<property name="visible">1</property>
- <property name="has-entry">1</property>
- <property name="halign">fill</property>
- <items>
- <item translatable="yes" id="Less than 15 minutes">Less than 15 minutes</item>
- <item translatable="yes" id="15 to 30 minutes">15 to 30 minutes</item>
- <item translatable="yes" id="30 to 45 minutes">30 to 45 minutes</item>
- <item translatable="yes" id="45 minutes to an hour">45 minutes to an hour</item>
- <item translatable="yes" id="More than an hour">More than an hour</item>
- </items>
+ <property name="label" translatable="yes">Description (optional)</property>
+ <property name="xalign">0</property>
+ <style> <class name="heading"/> </style>
</object>
<packing>
- <property name="left-attach">1</property>
- <property name="top-attach">4</property>
+ <property name="left-attach">0</property>
+ <property name="top-attach">9</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">1</property>
+ <property name="shadow-type">in</property>
+ <property name="min-content-height">120</property>
+ <child>
+ <object class="GtkTextView" id="description_field">
+ <property name="visible">1</property>
+ <property name="wrap-mode">word</property>
+ <property name="top-margin">10</property>
+ <property name="left-margin">10</property>
+ <property name="right-margin">10</property>
+ <property name="bottom-margin">10</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">10</property>
+ <property name="width">2</property>
</packing>
</child>
<child>
@@ -621,7 +573,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">5</property>
+ <property name="top-attach">11</property>
<property name="width">2</property>
</packing>
</child>
@@ -643,7 +595,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">6</property>
+ <property name="top-attach">12</property>
<property name="width">2</property>
</packing>
</child>
@@ -655,7 +607,7 @@
</object>
<packing>
<property name="left-attach">0</property>
- <property name="top-attach">7</property>
+ <property name="top-attach">13</property>
<property name="width">2</property>
</packing>
</child>
@@ -669,7 +621,6 @@
</child>
</template>
<object class="GtkPopover" id="ingredient_popover">
- <property name="relative-to">add_ingredient_button</property>
<property name="position">top</property>
<child>
<object class="GtkBox">
@@ -728,7 +679,7 @@
<property name="visible">1</property>
<property name="label" translatable="yes">Add</property>
<property name="halign">end</property>
- <signal name="clicked" handler="add_ingredient2" swapped="yes"/>
+ <signal name="clicked" handler="add_ingredient2"/>
</object>
</child>
</object>
diff --git a/src/gr-ingredients-list.c b/src/gr-ingredients-list.c
index 86d0ec4..51ff26f 100644
--- a/src/gr-ingredients-list.c
+++ b/src/gr-ingredients-list.c
@@ -43,6 +43,7 @@ typedef struct
gdouble value;
gchar *unit;
gchar *name;
+ gchar *segment;
} Ingredient;
static void
@@ -58,6 +59,7 @@ struct _GrIngredientsList
GObject parent_instance;
GList *ingredients;
+ GHashTable *segments;
};
G_DEFINE_TYPE (GrIngredientsList, gr_ingredients_list, G_TYPE_OBJECT)
@@ -222,6 +224,7 @@ parse_as_unit (Ingredient *ing,
static gboolean
gr_ingredients_list_add_one (GrIngredientsList *ingredients,
char *line,
+ char *segment,
GError **error)
{
Ingredient *ing;
@@ -250,6 +253,8 @@ gr_ingredients_list_add_one (GrIngredientsList *ingredients,
else
ing->name = g_strdup (line);
+ ing->segment = g_strdup (segment);
+
ingredients->ingredients = g_list_append (ingredients->ingredients, ing);
return TRUE;
@@ -262,15 +267,31 @@ gr_ingredients_list_populate (GrIngredientsList *ingredients,
{
g_auto(GStrv) lines = NULL;
int i;
+ g_autofree char *segment = NULL;
lines = g_strsplit (text, "\n", 0);
for (i = 0; lines[i]; i++) {
- if (!gr_ingredients_list_add_one (ingredients, lines[i], error))
+ char *p;
+ p = strrchr (lines[i], '\t');
+ if (p) {
+ segment = g_strdup (p + 1);
+ *p = 0;
+ }
+ else
+ segment = NULL;
+
+ if (segment)
+ g_hash_table_add (ingredients->segments, g_strdup (segment));
+ if (!gr_ingredients_list_add_one (ingredients, lines[i],
+ (char *)(segment ? segment : ""), error))
return FALSE;
}
- return TRUE;
+ if (g_hash_table_size (ingredients->segments) == 0)
+ g_hash_table_add (ingredients->segments, g_strdup (""));
+
+ return TRUE;
}
@@ -280,6 +301,7 @@ ingredients_list_finalize (GObject *object)
GrIngredientsList *self = GR_INGREDIENTS_LIST (object);
g_list_free_full (self->ingredients, (GDestroyNotify)ingredient_free);
+ g_hash_table_unref (self->segments);
G_OBJECT_CLASS (gr_ingredients_list_parent_class)->finalize (object);
}
@@ -287,6 +309,7 @@ ingredients_list_finalize (GObject *object)
static void
gr_ingredients_list_init (GrIngredientsList *ingredients)
{
+ ingredients->segments = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
static void
@@ -452,16 +475,24 @@ gr_ingredients_list_scale (GrIngredientsList *ingredients,
}
char **
-gr_ingredients_list_get_ingredients (GrIngredientsList *ingredients)
+gr_ingredients_list_get_segments (GrIngredientsList *ingredients)
+{
+ return (char **)g_hash_table_get_keys_as_array (ingredients->segments, NULL);
+}
+
+char **
+gr_ingredients_list_get_ingredients (GrIngredientsList *ingredients,
+ const char *segment)
{
char **ret;
int i;
GList *l;
ret = g_new0 (char *, g_list_length (ingredients->ingredients) + 1);
- for (i = 0, l = ingredients->ingredients; l; i++, l = l->next) {
+ for (i = 0, l = ingredients->ingredients; l; l = l->next) {
Ingredient *ing = (Ingredient *)l->data;
- ret[i] = g_strdup (ing->name);
+ if (g_strcmp0 (segment, ing->segment) == 0)
+ ret[i++] = g_strdup (ing->name);
}
return ret;
diff --git a/src/gr-ingredients-list.h b/src/gr-ingredients-list.h
index f15c9c7..086c647 100644
--- a/src/gr-ingredients-list.h
+++ b/src/gr-ingredients-list.h
@@ -39,7 +39,9 @@ char *gr_ingredients_list_scale_unit (GrIngredientsList *ingr
const char *name,
int num,
int denom);
-char **gr_ingredients_list_get_ingredients (GrIngredientsList *ingredients);
+char **gr_ingredients_list_get_segments (GrIngredientsList *ingredients);
+char **gr_ingredients_list_get_ingredients (GrIngredientsList *ingredients,
+ const char *segment);
G_END_DECLS
diff --git a/src/gr-recipe-store.c b/src/gr-recipe-store.c
index 400376d..dd2253d 100644
--- a/src/gr-recipe-store.c
+++ b/src/gr-recipe-store.c
@@ -1230,7 +1230,7 @@ gr_recipe_store_get_all_ingredients (GrRecipeStore *self,
GrRecipe *recipe;
GHashTable *ingreds;
char **result;
- int i;
+ int i, j;
ingreds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -1239,6 +1239,7 @@ gr_recipe_store_get_all_ingredients (GrRecipeStore *self,
const char *ingredients;
GrIngredientsList *list = NULL;
g_autofree char **ret = NULL;
+ g_autofree char **segments = NULL;
ingredients = gr_recipe_get_ingredients (recipe);
@@ -1246,9 +1247,12 @@ gr_recipe_store_get_all_ingredients (GrRecipeStore *self,
continue;
list = gr_ingredients_list_new (ingredients);
- ret = gr_ingredients_list_get_ingredients (list);
- for (i = 0; ret[i]; i++)
- g_hash_table_add (ingreds, ret[i]);
+ segments = gr_ingredients_list_get_segments (list);
+ for (j = 0; segments[j]; j++) {
+ ret = gr_ingredients_list_get_ingredients (list, segments[j]);
+ for (i = 0; ret[i]; i++)
+ g_hash_table_add (ingreds, ret[i]);
+ }
g_object_unref (list);
}
@@ -1307,7 +1311,6 @@ gr_recipe_store_remove_favorite (GrRecipeStore *self,
break;
}
}
-
save_favorites (self);
g_signal_emit (self, changed_signal, 0, recipe);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]