[gnome-control-center] printers: Allow undoing deletion of a printer



commit f065f5005f91362d5017c8e71db3e304bf53b60d
Author: Felipe Borges <felipeborges gnome org>
Date:   Tue Feb 21 18:03:27 2017 +0100

    printers: Allow undoing deletion of a printer
    
    Instead of directly applying the deletion of a printer, we should
    follow the GNOME in-app notification deletion guidelines.
    
    This patch introduces the in-app notification following the HIG[0]
    for the deletion of a printer. It allows to "undo" the deletion.
    
    The default behavior for these notification is to dismiss a previous
    notification. In doing so, when deleting multiple printers, the
    "Undo" button only restores the last deleted one. We don't do batch/
    bulk removal in the printers panel.
    
    [0] https://developer.gnome.org/hig/stable/in-app-notifications.html.en
    
    https://bugzilla.gnome.org/show_bug.cgi?id=693187

 panels/printers/cc-printers-panel.c |  134 ++++++++++++++++++++++++++++++++++-
 panels/printers/pp-printer-entry.c  |   27 +++----
 panels/printers/printers.ui         |   54 ++++++++++++++
 3 files changed, 196 insertions(+), 19 deletions(-)
---
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
index 4306829..449acec 100644
--- a/panels/printers/cc-printers-panel.c
+++ b/panels/printers/cc-printers-panel.c
@@ -89,6 +89,7 @@ struct _CcPrintersPanelPrivate
   guint            dbus_subscription_id;
 
   GtkWidget    *headerbar_buttons;
+  GtkRevealer  *notification;
   PPDList      *all_ppds_list;
   GCancellable *get_all_ppds_cancellable;
   GCancellable *subscription_renew_cancellable;
@@ -101,6 +102,7 @@ struct _CcPrintersPanelPrivate
   gboolean  select_new_printer;
 
   gchar    *renamed_printer_name;
+  gchar    *deleted_printer_name;
 
   GHashTable *printer_entries;
 
@@ -177,6 +179,23 @@ cc_printers_panel_constructed (GObject *object)
 }
 
 static void
+printer_removed_cb (GObject      *source_object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  GError *error = NULL;
+
+  pp_printer_delete_finish (PP_PRINTER (source_object), result, &error);
+  g_object_unref (source_object);
+
+  if (error != NULL)
+    {
+      g_warning ("Printer could not be deleted: %s", error->message);
+      g_error_free (error);
+    }
+}
+
+static void
 cc_printers_panel_dispose (GObject *object)
 {
   CcPrintersPanelPrivate *priv = CC_PRINTERS_PANEL (object)->priv;
@@ -237,6 +256,19 @@ cc_printers_panel_dispose (GObject *object)
       priv->get_all_ppds_cancellable = NULL;
     }
 
+  if (priv->deleted_printer_name != NULL)
+    {
+      PpPrinter *printer;
+
+      printer = pp_printer_new (priv->deleted_printer_name);
+      g_clear_pointer (&priv->deleted_printer_name, g_free);
+
+      pp_printer_delete_async (printer,
+                               NULL,
+                               printer_removed_cb,
+                               NULL);
+    }
+
   g_clear_pointer (&priv->printer_entries, g_hash_table_destroy);
 
   G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
@@ -589,6 +621,81 @@ free_dests (CcPrintersPanel *self)
 }
 
 static void
+on_printer_deletion_undone (GtkButton *button,
+                            gpointer   user_data)
+{
+  CcPrintersPanelPrivate *priv;
+  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
+
+  priv = PRINTERS_PANEL_PRIVATE (self);
+
+  gtk_revealer_set_reveal_child (priv->notification, FALSE);
+
+  g_clear_pointer (&priv->deleted_printer_name, g_free);
+  actualize_printers_list (self);
+}
+
+static void
+on_notification_dismissed (GtkButton *button,
+                           gpointer   user_data)
+{
+  CcPrintersPanelPrivate *priv;
+  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
+
+  priv = PRINTERS_PANEL_PRIVATE (self);
+
+  if (priv->deleted_printer_name != NULL)
+    {
+      PpPrinter *printer;
+
+      printer = pp_printer_new (priv->deleted_printer_name);
+      pp_printer_delete_async (printer,
+                               NULL,
+                               printer_removed_cb,
+                               NULL);
+
+      g_clear_pointer (&priv->deleted_printer_name, g_free);
+    }
+
+  gtk_revealer_set_reveal_child (priv->notification, FALSE);
+}
+
+static void
+on_printer_deleted (PpPrinterEntry *printer_entry,
+                    gpointer        user_data)
+{
+  CcPrintersPanelPrivate *priv;
+  CcPrintersPanel        *self = (CcPrintersPanel*) user_data;
+  GtkLabel               *label;
+  gchar                  *notification_message;
+  gchar                  *printer_name;
+
+  gtk_widget_hide (GTK_WIDGET (printer_entry));
+
+  priv = PRINTERS_PANEL_PRIVATE (self);
+
+  on_notification_dismissed (NULL, self);
+
+  g_object_get (printer_entry,
+                "printer-name", &printer_name,
+                NULL);
+
+  /* Translators: %s is the printer name */
+  notification_message = g_strdup_printf (_("Printer \"%s\" has been deleted"),
+                                          printer_name);
+  label = (GtkLabel*)
+    gtk_builder_get_object (priv->builder, "notification-label");
+  gtk_label_set_label (label, notification_message);
+
+  g_free (notification_message);
+
+  priv->deleted_printer_name = g_strdup (printer_name);
+  g_free (printer_name);
+
+  gtk_revealer_set_reveal_child (priv->notification, TRUE);
+}
+
+static void
 on_printer_changed (PpPrinterEntry *printer_entry,
                     gpointer        user_data)
 {
@@ -612,6 +719,10 @@ add_printer_entry (CcPrintersPanel *self,
                     "printer-changed",
                     G_CALLBACK (on_printer_changed),
                     self);
+  g_signal_connect (printer_entry,
+                    "printer-delete",
+                    G_CALLBACK (on_printer_deleted),
+                    self);
 
   gtk_list_box_insert (GTK_LIST_BOX (content), GTK_WIDGET (printer_entry), -1);
   gtk_widget_show_all (content);
@@ -679,7 +790,12 @@ actualize_printers_list_cb (GObject      *source_object,
   widget = (GtkWidget*) gtk_builder_get_object (priv->builder, "content");
   gtk_container_foreach (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_destroy, NULL);
   for (i = 0; i < priv->num_dests; i++)
-    add_printer_entry (self, priv->dests[i]);
+    {
+      if (g_strcmp0 (priv->dests[i].name, priv->deleted_printer_name) == 0)
+          continue;
+
+      add_printer_entry (self, priv->dests[i]);
+    }
 }
 
 static void
@@ -993,7 +1109,7 @@ cc_printers_panel_init (CcPrintersPanel *self)
   GtkWidget              *widget;
   PpCups                 *cups;
   GError                 *error = NULL;
-  gchar                  *objects[] = { "main-vbox", "headerbar-buttons", "search-button", NULL };
+  gchar                  *objects[] = { "overlay", "headerbar-buttons", "search-button", NULL };
   guint                   builder_result;
 
   priv = self->priv = PRINTERS_PANEL_PRIVATE (self);
@@ -1020,6 +1136,7 @@ cc_printers_panel_init (CcPrintersPanel *self)
   priv->select_new_printer = FALSE;
 
   priv->renamed_printer_name = NULL;
+  priv->deleted_printer_name = NULL;
 
   priv->permission = NULL;
   priv->lockdown_settings = NULL;
@@ -1049,9 +1166,20 @@ cc_printers_panel_init (CcPrintersPanel *self)
     gtk_builder_get_object (priv->builder, "headerbar-buttons");
   priv->headerbar_buttons = widget;
 
+  priv->notification = (GtkRevealer*)
+    gtk_builder_get_object (priv->builder, "notification");
+
+  widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "notification-undo-button");
+  g_signal_connect (widget, "clicked", G_CALLBACK (on_printer_deletion_undone), self);
+
+  widget = (GtkWidget*)
+    gtk_builder_get_object (priv->builder, "notification-dismiss-button");
+  g_signal_connect (widget, "clicked", G_CALLBACK (on_notification_dismissed), self);
+
   /* add the top level widget */
   top_widget = (GtkWidget*)
-    gtk_builder_get_object (priv->builder, "main-vbox");
+    gtk_builder_get_object (priv->builder, "overlay");
 
   /* connect signals */
   widget = (GtkWidget*)
diff --git a/panels/printers/pp-printer-entry.c b/panels/printers/pp-printer-entry.c
index a5851a7..c2011f8 100644
--- a/panels/printers/pp-printer-entry.c
+++ b/panels/printers/pp-printer-entry.c
@@ -81,6 +81,7 @@ struct _PpPrinterEntryClass
   GtkListBoxRowClass parent_class;
 
   void (*printer_changed) (PpPrinterEntry *printer_entry);
+  void (*printer_delete)  (PpPrinterEntry *printer_entry);
 };
 
 G_DEFINE_TYPE (PpPrinterEntry, pp_printer_entry, GTK_TYPE_LIST_BOX_ROW)
@@ -93,6 +94,7 @@ enum {
 
 enum {
   IS_DEFAULT_PRINTER,
+  PRINTER_DELETE,
   LAST_SIGNAL,
 };
 
@@ -530,25 +532,10 @@ clean_heads (GtkButton *button,
 }
 
 static void
-remove_printer_cb (GObject      *source_object,
-                   GAsyncResult *res,
-                   gpointer      user_data)
-{
-  pp_printer_delete_finish (PP_PRINTER (source_object), res, NULL);
-  g_object_unref (source_object);
-}
-
-static void
 remove_printer (GtkButton      *button,
                 PpPrinterEntry *self)
 {
-  PpPrinter *printer;
-
-  printer = pp_printer_new (self->printer_name);
-  pp_printer_delete_async (printer,
-                           NULL,
-                           remove_printer_cb,
-                           NULL);
+  g_signal_emit_by_name (self, "printer-delete", self->printer_name);
 }
 
 static void
@@ -1041,4 +1028,12 @@ pp_printer_entry_class_init (PpPrinterEntryClass *klass)
                   G_STRUCT_OFFSET (PpPrinterEntryClass, printer_changed),
                   NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
+
+  signals[PRINTER_DELETE] =
+    g_signal_new ("printer-delete",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (PpPrinterEntryClass, printer_delete),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
 }
diff --git a/panels/printers/printers.ui b/panels/printers/printers.ui
index ec93ed4..9dcf0cb 100644
--- a/panels/printers/printers.ui
+++ b/panels/printers/printers.ui
@@ -42,6 +42,56 @@
     </child>
   </object>
 
+<object class="GtkOverlay" id="overlay">
+  <property name="visible">True</property>
+  <child type="overlay">
+    <object class="GtkRevealer" id="notification">
+      <property name="visible">True</property>
+      <property name="halign">GTK_ALIGN_CENTER</property>
+      <property name="valign">GTK_ALIGN_START</property>
+      <child>
+        <object class="GtkBox">
+          <property name="visible">True</property>
+          <property name="spacing">6</property>
+          <style>
+            <class name="app-notification"/>
+          </style>
+          <child>
+            <object class="GtkLabel" id="notification-label">
+              <property name="visible">True</property>
+              <property name="wrap">True</property>
+              <property name="max_width_chars">50</property>
+            </object>
+          </child>
+          <child>
+            <object class="GtkButton" id="notification-undo-button">
+              <property name="visible">True</property>
+              <property name="can_focus">True</property>
+              <property name="valign">GTK_ALIGN_CENTER</property>
+              <property name="label" translatable="yes" comments="Translators: This is the button which 
allows undoing the removal of the printer.">Undo</property>
+            </object>
+          </child>
+          <child>
+            <object class="GtkButton" id="notification-dismiss-button">
+              <property name="visible">True</property>
+              <property name="valign">GTK_ALIGN_CENTER</property>
+              <style>
+                <class name="flat"/>
+              </style>
+              <child>
+                <object class="GtkImage">
+                  <property name="visible">True</property>
+                  <property name="icon_name">window-close-symbolic</property>
+                </object>
+              </child>
+            </object>
+          </child>
+        </object>
+      </child>
+    </object>
+  </child>
+  <child>
+
   <object class="GtkStack" id="main-vbox">
     <child>
       <object class="GtkBox">
@@ -209,6 +259,10 @@ doesn’t seem to be available.</property>
       </packing>
     </child>
   </object>
+
+  </child>
+</object>
+
   <object class="GtkSizeGroup" id="sizegroup1">
    <widgets>
       <widget name="back-button-1"/>


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