[gnome-control-center] Printers: Add authentication dialog for print jobs



commit 1be3901b67867477f82c462aaa2f4fca5eebe01e
Author: Marek Kasik <mkasik redhat com>
Date:   Mon Feb 19 01:02:32 2018 +0100

    Printers: Add authentication dialog for print jobs
    
    This commit adds popup dialog to jobs dialog which can be accessed
    if there is a print job which needs authentication.
    Clicking "Authenticate" button will reveal this dialog
    where user can enter credential info for the actual printer
    and clicking the "Authenticate" in it will authenticate all
    print jobs of this printer which needs authentication info
    and will send them for printing.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=758170

 panels/printers/jobs-dialog.ui   | 273 +++++++++++++++++++++++++++++++-
 panels/printers/pp-jobs-dialog.c | 332 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 580 insertions(+), 25 deletions(-)
---
diff --git a/panels/printers/jobs-dialog.ui b/panels/printers/jobs-dialog.ui
index 579b58f0e..0542538ad 100644
--- a/panels/printers/jobs-dialog.ui
+++ b/panels/printers/jobs-dialog.ui
@@ -1,7 +1,148 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.20.2 -->
 <interface>
-  <requires lib="gtk+" version="3.12"/>
+  <requires lib="gtk+" version="3.22"/>
+  <object class="GtkPopover" id="authentication_popover">
+    <property name="can_focus">False</property>
+    <property name="halign">start</property>
+    <property name="valign">start</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin_left">30</property>
+        <property name="margin_right">30</property>
+        <property name="margin_top">20</property>
+        <property name="margin_bottom">20</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">20</property>
+        <child>
+          <object class="GtkLabel" id="authentication-label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_top">5</property>
+            <property name="margin_bottom">5</property>
+            <property name="label" translatable="no">Enter credentials to print from %s.</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="row_spacing">10</property>
+            <property name="column_spacing">15</property>
+            <child>
+              <object class="GtkLabel" id="domain-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes" comments="Translators: This is a windows domain 
used with SMB protocol.">Domain</property>
+                <property name="xalign">1</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="username-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes" comments="Translators: This is a username on a 
print server.">Username</property>
+                <property name="xalign">1</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="password-label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">start</property>
+                <property name="label" translatable="yes" comments="Translators: This is a password needed 
for printing.">Password</property>
+                <property name="xalign">1</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="domain-entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="username-entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="password-entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="visibility">False</property>
+                <property name="invisible_char">*</property>
+                <property name="input_purpose">password</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="authenticate-button">
+            <property name="label" translatable="yes" comments="Translators: This button authenticates all 
print jobs and send them for printing.">A_uthenticate</property>
+            <property name="use_underline">True</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="halign">end</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkSizeGroup">
+    <widgets>
+      <widget name="domain-label"/>
+      <widget name="username-label"/>
+      <widget name="password-label"/>
+    </widgets>
+  </object>
   <object class="GtkDialog" id="jobs-dialog">
     <property name="width_request">600</property>
     <property name="height_request">500</property>
@@ -39,9 +180,125 @@
         <style>
           <class name="view"/>
         </style>
+        <property name="orientation">vertical</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkInfoBar" id="authentication-infobar">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">0</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">12</property>
+            <child internal-child="action_area">
+              <object class="GtkButtonBox">
+                <property name="can_focus">False</property>
+                <property name="border_width">12</property>
+                <property name="spacing">6</property>
+                <property name="layout_style">end</property>
+                <property name="margin-end">2</property>
+                <child>
+                  <object class="GtkMenuButton" id="authenticate-jobs-button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="halign">end</property>
+                    <property name="popover">authentication_popover</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="spacing">5</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="use_underline">True</property>
+                            <property name="label" translatable="yes" comments="Translators: This button pop 
up authentication dialog for print jobs which need credentials.">_Authenticate</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkArrow">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="arrow_type">down</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="pack_type">end</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child internal-child="content_area">
+              <object class="GtkBox">
+                <property name="can_focus">False</property>
+                <property name="spacing">16</property>
+                <property name="margin-start">12</property>
+                <child>
+                  <object class="GtkLabel" id="authenticate-jobs-label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="hexpand">False</property>
+                    <property name="label" translatable="no">2 Jobs Require Authentication</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkStack" id="stack">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <child>
               <object class="GtkScrolledWindow" id="scrolledwindow">
                 <property name="visible">True</property>
@@ -93,23 +350,35 @@
                 <child>
                   <object class="GtkLabel" id="no-printer-label">
                     <property name="visible">True</property>
+                    <property name="can_focus">False</property>
                     <property name="label" translatable="yes" comments="Translators: this label describes 
the dialog empty state, with no jobs listed.">No Active Printer Jobs</property>
                     <style>
                       <class name="dim-label"/>
                     </style>
                   </object>
                   <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
                     <property name="position">1</property>
                   </packing>
                 </child>
               </object>
               <packing>
                 <property name="name">no-jobs-page</property>
+                <property name="position">1</property>
               </packing>
             </child>
           </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
         </child>
       </object>
     </child>
+    <child>
+      <placeholder/>
+    </child>
   </object>
 </interface>
diff --git a/panels/printers/pp-jobs-dialog.c b/panels/printers/pp-jobs-dialog.c
index 6971256c4..7b2993114 100644
--- a/panels/printers/pp-jobs-dialog.c
+++ b/panels/printers/pp-jobs-dialog.c
@@ -58,9 +58,141 @@ struct _PpJobsDialog {
 
   gchar *printer_name;
 
+  gchar    **actual_auth_info_required;
+
   GCancellable *get_jobs_cancellable;
 };
 
+static gboolean
+is_info_required (PpJobsDialog *dialog,
+                  const gchar  *info)
+{
+  gboolean   required = FALSE;
+  gint       i;
+
+  if (dialog != NULL && dialog->actual_auth_info_required != NULL)
+    {
+      for (i = 0; dialog->actual_auth_info_required[i] != NULL; i++)
+        {
+          if (g_strcmp0 (dialog->actual_auth_info_required[i], info) == 0)
+            {
+              required = TRUE;
+              break;
+            }
+        }
+    }
+
+  return required;
+}
+
+static gboolean
+is_domain_required (PpJobsDialog *dialog)
+{
+  return is_info_required (dialog, "domain");
+}
+
+static gboolean
+is_username_required (PpJobsDialog *dialog)
+{
+  return is_info_required (dialog, "username");
+}
+
+static gboolean
+is_password_required (PpJobsDialog *dialog)
+{
+  return is_info_required (dialog, "password");
+}
+
+static gboolean
+auth_popup_filled (PpJobsDialog *dialog)
+{
+  gboolean domain_required;
+  gboolean username_required;
+  gboolean password_required;
+  guint16  domain_length;
+  guint16  username_length;
+  guint16  password_length;
+
+  domain_required = is_domain_required (dialog);
+  username_required = is_username_required (dialog);
+  password_required = is_password_required (dialog);
+
+  domain_length = gtk_entry_get_text_length (GTK_ENTRY (gtk_builder_get_object (dialog->builder, 
"domain-entry")));
+  username_length = gtk_entry_get_text_length (GTK_ENTRY (gtk_builder_get_object (dialog->builder, 
"username-entry")));
+  password_length = gtk_entry_get_text_length (GTK_ENTRY (gtk_builder_get_object (dialog->builder, 
"password-entry")));
+
+  return (!domain_required || domain_length > 0) &&
+         (!username_required || username_length > 0) &&
+         (!password_required || password_length > 0);
+}
+
+static void
+auth_entries_changed (GtkEntry     *entry,
+                      PpJobsDialog *dialog)
+{
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "authenticate-button"));
+  gtk_widget_set_sensitive (widget, auth_popup_filled (dialog));
+}
+
+static void
+auth_entries_activated (GtkEntry     *entry,
+                        PpJobsDialog *dialog)
+{
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "authenticate-button"));
+  if (auth_popup_filled (dialog))
+    gtk_button_clicked (GTK_BUTTON (widget));
+}
+
+static void
+authenticate_popover_update (PpJobsDialog *dialog)
+{
+  GtkWidget *widget;
+  gboolean   domain_required;
+  gboolean   username_required;
+  gboolean   password_required;
+
+  domain_required = is_domain_required (dialog);
+  username_required = is_username_required (dialog);
+  password_required = is_password_required (dialog);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "domain-label"));
+  gtk_widget_set_visible (widget, domain_required);
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "domain-entry"));
+  gtk_widget_set_visible (widget, domain_required);
+  if (domain_required)
+    {
+      gtk_entry_set_text (GTK_ENTRY (widget), "");
+      gtk_entry_grab_focus_without_selecting (GTK_ENTRY (widget));
+    }
+
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "username-label"));
+  gtk_widget_set_visible (widget, username_required);
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "username-entry"));
+  gtk_widget_set_visible (widget, username_required);
+  if (username_required)
+    {
+      gtk_entry_set_text (GTK_ENTRY (widget), cupsUser ());
+      gtk_entry_grab_focus_without_selecting (GTK_ENTRY (widget));
+    }
+
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "password-label"));
+  gtk_widget_set_visible (widget, password_required);
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "password-entry"));
+  gtk_widget_set_visible (widget, password_required);
+  if (password_required)
+    {
+      gtk_entry_set_text (GTK_ENTRY (widget), "");
+      gtk_entry_grab_focus_without_selecting (GTK_ENTRY (widget));
+    }
+
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "authenticate-button"));
+  gtk_widget_set_sensitive (widget, FALSE);
+}
+
 static void
 job_stop_cb (GtkButton *button,
              PpJob     *job)
@@ -88,14 +220,19 @@ static GtkWidget *
 create_listbox_row (gpointer item,
                     gpointer user_data)
 {
-  PpJob     *job = (PpJob *)item;
-  GtkWidget *box;
-  GtkWidget *widget;
-  gchar     *title;
-  gchar     *state_string = NULL;
-  gint       job_state;
-
-  g_object_get (job, "title", &title, "state", &job_state, NULL);
+  GtkWidget  *widget;
+  GtkWidget  *box;
+  PpJob      *job = (PpJob *)item;
+  gchar     **auth_info_required;
+  gchar      *title;
+  gchar      *state_string = NULL;
+  gint        job_state;
+
+  g_object_get (job,
+                "title", &title,
+                "state", &job_state,
+                "auth-info-required", &auth_info_required,
+                NULL);
 
   switch (job_state)
     {
@@ -104,8 +241,16 @@ create_listbox_row (gpointer item,
         state_string = g_strdup (C_("print job", "Pending"));
         break;
       case IPP_JOB_HELD:
-        /* Translators: Job's state (job is held for printing) */
-        state_string = g_strdup (C_("print job", "Paused"));
+        if (auth_info_required == NULL)
+          {
+            /* Translators: Job's state (job is held for printing) */
+            state_string = g_strdup (C_("print job", "Paused"));
+          }
+        else
+          {
+            /* Translators: Job's state (job needs authentication to proceed further) */
+            state_string = g_strdup_printf ("<span foreground=\"#ff0000\">%s</span>", C_("print job", 
"Authentication required"));
+          }
         break;
       case IPP_JOB_PROCESSING:
         /* Translators: Job's state (job is currently printing) */
@@ -137,14 +282,17 @@ create_listbox_row (gpointer item,
   gtk_widget_set_halign (widget, GTK_ALIGN_START);
   gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 10);
 
-  widget = gtk_label_new (state_string);
+  widget = gtk_label_new (NULL);
+  gtk_label_set_markup (GTK_LABEL (widget), state_string);
   gtk_widget_set_halign (widget, GTK_ALIGN_END);
   gtk_widget_set_margin_end (widget, 64);
+  gtk_widget_set_margin_start (widget, 64);
   gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 10);
 
   widget = gtk_button_new_from_icon_name (job_state == IPP_JOB_HELD ? "media-playback-start-symbolic" : 
"media-playback-pause-symbolic",
                                           GTK_ICON_SIZE_SMALL_TOOLBAR);
   g_signal_connect (widget, "clicked", G_CALLBACK (job_pause_cb), item);
+  gtk_widget_set_sensitive (widget, auth_info_required == NULL);
   gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 4);
 
   widget = gtk_button_new_from_icon_name ("edit-delete-symbolic",
@@ -162,13 +310,18 @@ update_jobs_list_cb (GObject      *source_object,
                      GAsyncResult *result,
                      gpointer      user_data)
 {
-  PpJobsDialog *dialog = user_data;
-  PpPrinter    *printer = PP_PRINTER (source_object);
-  GtkWidget    *clear_all_button;
-  GtkStack     *stack;
-  GError       *error = NULL;
-  GList        *jobs, *l;
-  gint          num_of_jobs;
+  PpJobsDialog  *dialog = user_data;
+  PpPrinter     *printer = PP_PRINTER (source_object);
+  GtkWidget     *clear_all_button;
+  GtkWidget     *infobar;
+  GtkWidget     *label;
+  GtkStack      *stack;
+  GError        *error = NULL;
+  GList         *jobs, *l;
+  PpJob         *job;
+  gchar        **auth_info_required = NULL;
+  gchar         *text;
+  gint           num_of_jobs, num_of_auth_jobs = 0;
 
   g_list_store_remove_all (dialog->store);
 
@@ -201,8 +354,44 @@ update_jobs_list_cb (GObject      *source_object,
 
   for (l = jobs; l != NULL; l = l->next)
     {
-      g_list_store_append (dialog->store, l->data);
+      job = PP_JOB (l->data);
+
+      g_list_store_append (dialog->store, job);
+
+      g_object_get (G_OBJECT (job),
+                    "auth-info-required", &auth_info_required,
+                    NULL);
+      if (auth_info_required != NULL)
+        {
+          num_of_auth_jobs++;
+
+          if (dialog->actual_auth_info_required == NULL)
+            dialog->actual_auth_info_required = auth_info_required;
+          else
+            g_strfreev (auth_info_required);
+
+          auth_info_required = NULL;
+        }
+    }
+
+  infobar = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "authentication-infobar"));
+  if (num_of_auth_jobs > 0)
+    {
+      label = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "authenticate-jobs-label"));
+
+      /* Translators: This label shows how many jobs of this printer needs to be authenticated to be 
printed. */
+      text = g_strdup_printf (ngettext ("%u Job Requires Authentication", "%u Jobs Require Authentication", 
num_of_auth_jobs), num_of_auth_jobs);
+      gtk_label_set_text (GTK_LABEL (label), text);
+      g_free (text);
+
+      gtk_widget_show (infobar);
     }
+  else
+    {
+      gtk_widget_hide (infobar);
+    }
+
+  authenticate_popover_update (dialog);
 
   g_list_free (jobs);
   g_clear_object (&dialog->get_jobs_cancellable);
@@ -265,6 +454,78 @@ on_clear_all_button_clicked (GtkButton *button,
     }
 }
 
+static void
+pp_job_authenticate_cb (GObject      *source_object,
+                        GAsyncResult *res,
+                        gpointer      user_data)
+{
+  PpJobsDialog *dialog = user_data;
+  gboolean      result;
+  GError       *error = NULL;
+  PpJob        *job = PP_JOB (source_object);
+
+  result = pp_job_authenticate_finish (job, res, &error);
+  if (result)
+    {
+      pp_jobs_dialog_update (dialog);
+    }
+  else if (error != NULL)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        {
+          g_warning ("Could not authenticate job: %s", error->message);
+        }
+
+      g_error_free (error);
+    }
+}
+
+static void
+authenticate_button_clicked (GtkWidget *button,
+                             gpointer   user_data)
+{
+  PpJobsDialog *dialog = user_data;
+  GtkWidget    *widget;
+  PpJob        *job;
+  gchar       **auth_info_required = NULL;
+  gchar       **auth_info;
+  guint         num_items;
+  gint          i;
+
+  auth_info = g_new0 (gchar *, g_strv_length (dialog->actual_auth_info_required) + 1);
+  for (i = 0; dialog->actual_auth_info_required[i] != NULL; i++)
+    {
+      if (g_strcmp0 (dialog->actual_auth_info_required[i], "domain") == 0)
+        widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "domain-entry"));
+      else if (g_strcmp0 (dialog->actual_auth_info_required[i], "username") == 0)
+        widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "username-entry"));
+      else if (g_strcmp0 (dialog->actual_auth_info_required[i], "password") == 0)
+        widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "password-entry"));
+      else
+        widget = NULL;
+
+      if (widget != NULL)
+        auth_info[i] = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
+    }
+
+  num_items = g_list_model_get_n_items (G_LIST_MODEL (dialog->store));
+  for (i = 0; i < num_items; i++)
+    {
+      job = PP_JOB (g_list_model_get_item (G_LIST_MODEL (dialog->store), i));
+
+      g_object_get (job, "auth-info-required", &auth_info_required, NULL);
+      if (auth_info_required != NULL)
+        {
+          pp_job_authenticate_async (job, auth_info, NULL, pp_job_authenticate_cb, dialog);
+
+          g_strfreev (auth_info_required);
+          auth_info_required = NULL;
+        }
+    }
+
+  g_strfreev (auth_info);
+}
+
 PpJobsDialog *
 pp_jobs_dialog_new (GtkWindow            *parent,
                     UserResponseCallback  user_callback,
@@ -272,9 +533,10 @@ pp_jobs_dialog_new (GtkWindow            *parent,
                     gchar                *printer_name)
 {
   PpJobsDialog    *dialog;
-  GtkButton       *clear_all_button;
+  GtkWidget       *widget;
   GError          *error = NULL;
-  gchar           *objects[] = { "jobs-dialog", NULL };
+  gchar           *objects[] = { "jobs-dialog", "authentication_popover", NULL };
+  gchar           *text;
   guint            builder_result;
   gchar           *title;
 
@@ -298,19 +560,41 @@ pp_jobs_dialog_new (GtkWindow            *parent,
   dialog->user_callback = user_callback;
   dialog->user_data = user_data;
   dialog->printer_name = g_strdup (printer_name);
+  dialog->actual_auth_info_required = NULL;
 
   /* connect signals */
   g_signal_connect (dialog->dialog, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
   g_signal_connect (dialog->dialog, "response", G_CALLBACK (jobs_dialog_response_cb), dialog);
 
-  clear_all_button = GTK_BUTTON (gtk_builder_get_object (dialog->builder, "jobs-clear-all-button"));
-  g_signal_connect (clear_all_button, "clicked", G_CALLBACK (on_clear_all_button_clicked), dialog);
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "jobs-clear-all-button"));
+  g_signal_connect (widget, "clicked", G_CALLBACK (on_clear_all_button_clicked), dialog);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "authenticate-button"));
+  g_signal_connect (widget, "clicked", G_CALLBACK (authenticate_button_clicked), dialog);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "domain-entry"));
+  g_signal_connect (widget, "changed", G_CALLBACK (auth_entries_changed), dialog);
+  g_signal_connect (widget, "activate", G_CALLBACK (auth_entries_activated), dialog);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "username-entry"));
+  g_signal_connect (widget, "changed", G_CALLBACK (auth_entries_changed), dialog);
+  g_signal_connect (widget, "activate", G_CALLBACK (auth_entries_activated), dialog);
+
+  widget = GTK_WIDGET (gtk_builder_get_object (dialog->builder, "password-entry"));
+  g_signal_connect (widget, "changed", G_CALLBACK (auth_entries_changed), dialog);
+  g_signal_connect (widget, "activate", G_CALLBACK (auth_entries_activated), dialog);
 
   /* Translators: This is the printer name for which we are showing the active jobs */
   title = g_strdup_printf (C_("Printer jobs dialog title", "%s — Active Jobs"), printer_name);
   gtk_window_set_title (GTK_WINDOW (dialog->dialog), title);
   g_free (title);
 
+  /* Translators: The printer needs authentication info to print. */
+  text = g_strdup_printf (_("Enter credentials to print from %s."), printer_name);
+  widget = GTK_WIDGET (gtk_builder_get_object (GTK_BUILDER (dialog->builder), "authentication-label"));
+  gtk_label_set_text (GTK_LABEL (widget), text);
+  g_free (text);
+
   dialog->listbox = GTK_LIST_BOX (gtk_builder_get_object (dialog->builder, "jobs-listbox"));
   gtk_list_box_set_header_func (dialog->listbox,
                                 cc_list_box_update_header_func, NULL, NULL);
@@ -357,6 +641,8 @@ pp_jobs_dialog_free (PpJobsDialog *dialog)
   gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
   dialog->dialog = NULL;
 
+  g_strfreev (dialog->actual_auth_info_required);
+
   g_clear_object (&dialog->builder);
   g_free (dialog->printer_name);
   g_free (dialog);


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