[recipes] Add an undo notification for deleting recipes
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Add an undo notification for deleting recipes
- Date: Tue, 10 Jan 2017 02:34:17 +0000 (UTC)
commit 7ca7115dfcc00e83432f1a3c61797dadd113e6fc
Author: Matthias Clasen <mclasen redhat com>
Date: Mon Jan 9 21:33:19 2017 -0500
Add an undo notification for deleting recipes
The implementation is inspired by the corresponding feature
in nautilus. We show the notification for 10 seconds.
src/gr-details-page.c | 5 ++
src/gr-window.c | 66 ++++++++++++++++++++
src/gr-window.h | 2 +
src/gr-window.ui | 160 +++++++++++++++++++++++++++++++++---------------
4 files changed, 183 insertions(+), 50 deletions(-)
---
diff --git a/src/gr-details-page.c b/src/gr-details-page.c
index 1da9969..d85a349 100644
--- a/src/gr-details-page.c
+++ b/src/gr-details-page.c
@@ -246,8 +246,11 @@ static void
delete_recipe (GrDetailsPage *page)
{
GrRecipeStore *store;
+ g_autoptr(GrRecipe) recipe = NULL;
GtkWidget *window;
+ recipe = g_object_ref (page->recipe);
+
store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
gr_recipe_store_remove_recipe (store, page->recipe);
g_set_object (&page->recipe, NULL);
@@ -255,6 +258,8 @@ delete_recipe (GrDetailsPage *page)
window = gtk_widget_get_ancestor (GTK_WIDGET (page), GTK_TYPE_APPLICATION_WINDOW);
gr_window_go_back (GR_WINDOW (window));
+
+ gr_window_offer_undelete (GR_WINDOW (window), recipe);
}
static void
diff --git a/src/gr-window.c b/src/gr-window.c
index ab782c6..c58c8e5 100644
--- a/src/gr-window.c
+++ b/src/gr-window.c
@@ -57,6 +57,10 @@ struct _GrWindow
GtkWidget *cuisines_page;
GtkWidget *cuisine_page;
GtkWidget *ingredients_page;
+ GtkWidget *undo_revealer;
+ GtkWidget *undo_label;
+ GrRecipe *undo_recipe;
+ guint undo_timeout_id;
GrRecipeImporter *importer;
@@ -343,10 +347,68 @@ gr_window_finalize (GObject *object)
g_clear_object (&self->importer);
+ if (self->undo_timeout_id) {
+ g_source_remove (self->undo_timeout_id);
+ self->undo_timeout_id = 0;
+ }
+
G_OBJECT_CLASS (gr_window_parent_class)->finalize (object);
}
static void
+close_undo (GrWindow *window)
+{
+ if (window->undo_timeout_id) {
+ g_source_remove (window->undo_timeout_id);
+ window->undo_timeout_id = 0;
+ }
+
+ g_clear_object (&window->undo_recipe);
+
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->undo_revealer), FALSE);
+}
+
+static void
+do_undo (GrWindow *window)
+{
+ GrRecipeStore *store;
+ g_autoptr(GrRecipe) recipe = NULL;
+
+ recipe = g_object_ref (window->undo_recipe);
+
+ store = gr_app_get_recipe_store (GR_APP (g_application_get_default ()));
+
+ gr_recipe_store_add_recipe (store, window->undo_recipe, NULL);
+ close_undo (window);
+
+ gr_window_show_recipe (window, recipe);
+}
+
+static gboolean
+undo_timeout (gpointer data)
+{
+ GrWindow *window = data;
+
+ close_undo (window);
+
+ return G_SOURCE_REMOVE;
+}
+
+void
+gr_window_offer_undelete (GrWindow *window,
+ GrRecipe *recipe)
+{
+ g_autofree char *tmp = NULL;
+
+ window->undo_recipe = g_object_ref (recipe);
+ tmp = g_strdup_printf (_("Recipe ā%sā deleted"), gr_recipe_get_name (recipe));
+ gtk_label_set_label (GTK_LABEL (window->undo_label), tmp);
+
+ gtk_revealer_set_reveal_child (GTK_REVEALER (window->undo_revealer), TRUE);
+ window->undo_timeout_id = g_timeout_add_seconds (10, undo_timeout, window);
+}
+
+static void
gr_window_class_init (GrWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -372,6 +434,8 @@ gr_window_class_init (GrWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, GrWindow, cuisines_page);
gtk_widget_class_bind_template_child (widget_class, GrWindow, cuisine_page);
gtk_widget_class_bind_template_child (widget_class, GrWindow, ingredients_page);
+ gtk_widget_class_bind_template_child (widget_class, GrWindow, undo_revealer);
+ gtk_widget_class_bind_template_child (widget_class, GrWindow, undo_label);
gtk_widget_class_bind_template_callback (widget_class, new_recipe);
gtk_widget_class_bind_template_callback (widget_class, go_back);
@@ -383,6 +447,8 @@ gr_window_class_init (GrWindowClass *klass)
gtk_widget_class_bind_template_callback (widget_class, stop_search);
gtk_widget_class_bind_template_callback (widget_class, window_keypress_handler);
gtk_widget_class_bind_template_callback (widget_class, window_mapped_handler);
+ gtk_widget_class_bind_template_callback (widget_class, do_undo);
+ gtk_widget_class_bind_template_callback (widget_class, close_undo);
}
static void
diff --git a/src/gr-window.h b/src/gr-window.h
index 51ee8ea..990cbe2 100644
--- a/src/gr-window.h
+++ b/src/gr-window.h
@@ -59,5 +59,7 @@ void gr_window_show_season (GrWindow *window,
const char *title);
void gr_window_show_search_by_ingredients (GrWindow *window,
const char *ingredient);
+void gr_window_offer_undelete (GrWindow *window,
+ GrRecipe *recipe);
G_END_DECLS
diff --git a/src/gr-window.ui b/src/gr-window.ui
index 2a9829e..7d2ae69 100644
--- a/src/gr-window.ui
+++ b/src/gr-window.ui
@@ -162,59 +162,119 @@
</object>
</child>
<child>
- <object class="GtkStack" id="main_stack">
+ <object class="GtkOverlay">
<property name="visible">1</property>
- <signal name="notify::visible-child-name" handler="visible_page_changed" swapped="yes"/>
- <child>
- <object class="GrRecipesPage" id="recipes_page"/>
- <packing>
- <property name="name">recipes</property>
- <property name="title" translatable="yes">Recipes</property>
- </packing>
- </child>
- <child>
- <object class="GrListPage" id="list_page"/>
- <packing>
- <property name="name">list</property>
- </packing>
- </child>
- <child>
- <object class="GrSearchPage" id="search_page"/>
- <packing>
- <property name="name">search</property>
- </packing>
- </child>
- <child>
- <object class="GrCuisinesPage" id="cuisines_page"/>
- <packing>
- <property name="name">cuisines</property>
- <property name="title" translatable="yes">Cuisines</property>
- </packing>
- </child>
- <child>
- <object class="GrCuisinePage" id="cuisine_page"/>
- <packing>
- <property name="name">cuisine</property>
- </packing>
- </child>
- <child>
- <object class="GrIngredientsPage" id="ingredients_page"/>
- <packing>
- <property name="name">ingredients</property>
- <property name="title" translatable="yes">Ingredients</property>
- </packing>
- </child>
- <child>
- <object class="GrDetailsPage" id="details_page"/>
- <packing>
- <property name="name">details</property>
- </packing>
+ <child type="overlay">
+ <object class="GtkRevealer" id="undo_revealer">
+ <property name="visible">1</property>
+ <property name="halign">center</property>
+ <property name="valign">start</property>
+ <child>
+ <object class="GtkFrame">
+ <property name="visible">1</property>
+ <style>
+ <class name="app-notification"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">1</property>
+ <property name="spacing">20</property>
+ <property name="margin">10</property>
+ <child>
+ <object class="GtkLabel" id="undo_label">
+ <property name="visible">1</property>
+ <property name="hexpand">1</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">1</property>
+ <property name="focus-on-click">0</property>
+ <property name="label" translatable="yes">Undo</property>
+ <signal name="clicked" handler="do_undo" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">1</property>
+ <property name="focus-on-click">0</property>
+ <property name="relief">none</property>
+ <signal name="clicked" handler="close_undo" swapped="yes"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="icon-name">window-close-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
</child>
<child>
- <object class="GrEditPage" id="edit_page"/>
- <packing>
- <property name="name">edit</property>
- </packing>
+ <object class="GtkStack" id="main_stack">
+ <property name="visible">1</property>
+ <signal name="notify::visible-child-name" handler="visible_page_changed" swapped="yes"/>
+ <child>
+ <object class="GrRecipesPage" id="recipes_page"/>
+ <packing>
+ <property name="name">recipes</property>
+ <property name="title" translatable="yes">Recipes</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrListPage" id="list_page"/>
+ <packing>
+ <property name="name">list</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrSearchPage" id="search_page"/>
+ <packing>
+ <property name="name">search</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrCuisinesPage" id="cuisines_page"/>
+ <packing>
+ <property name="name">cuisines</property>
+ <property name="title" translatable="yes">Cuisines</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrCuisinePage" id="cuisine_page"/>
+ <packing>
+ <property name="name">cuisine</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrIngredientsPage" id="ingredients_page"/>
+ <packing>
+ <property name="name">ingredients</property>
+ <property name="title" translatable="yes">Ingredients</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrDetailsPage" id="details_page"/>
+ <packing>
+ <property name="name">details</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GrEditPage" id="edit_page"/>
+ <packing>
+ <property name="name">edit</property>
+ </packing>
+ </child>
+ </object>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]