[gnome-control-center/wip/feborges/new-printers-panel] printers: redesign the Printer Jobs Dialog



commit 0e811619590f8a7e72c4f8c695dca8ca75790c2f
Author: Felipe Borges <feborges redhat com>
Date:   Tue Sep 8 16:55:38 2015 +0200

    printers: redesign the Printer Jobs Dialog
    
    Update the Printer Jobs Dialog to match the current designs at
    https://wiki.gnome.org/Design/SystemSettings/Printers

 panels/printers/Makefile.am      |    2 +
 panels/printers/jobs-dialog.ui   |  174 +++++-----------
 panels/printers/pp-job.c         |  138 ++++++++++++
 panels/printers/pp-job.h         |   40 ++++
 panels/printers/pp-jobs-dialog.c |  429 ++++++++++++++------------------------
 panels/printers/pp-utils.c       |   20 ++
 panels/printers/pp-utils.h       |    7 +
 7 files changed, 411 insertions(+), 399 deletions(-)
---
diff --git a/panels/printers/Makefile.am b/panels/printers/Makefile.am
index c386486..7fb2c17 100644
--- a/panels/printers/Makefile.am
+++ b/panels/printers/Makefile.am
@@ -37,6 +37,8 @@ libprinters_la_SOURCES =              \
        pp-ppd-selection-dialog.h       \
        pp-options-dialog.c             \
        pp-options-dialog.h             \
+       pp-job.c                        \
+       pp-job.h                        \
        pp-jobs-dialog.c                \
        pp-jobs-dialog.h                \
        pp-authentication-dialog.c      \
diff --git a/panels/printers/jobs-dialog.ui b/panels/printers/jobs-dialog.ui
index 6ac05a3..a3ea797 100644
--- a/panels/printers/jobs-dialog.ui
+++ b/panels/printers/jobs-dialog.ui
@@ -3,143 +3,67 @@
 <interface>
   <requires lib="gtk+" version="3.12"/>
   <object class="GtkDialog" id="jobs-dialog">
-    <property name="width_request">500</property>
-    <property name="height_request">350</property>
+    <property name="width_request">600</property>
+    <property name="height_request">500</property>
     <property name="can_focus">False</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes" comments="Translators: This dialog contains list of active 
print jobs of the selected printer">Active Jobs</property>
+    <property name="border_width">0</property>
     <property name="resizable">False</property>
     <property name="modal">True</property>
     <property name="destroy_with_parent">True</property>
     <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="main-vbox">
+    <property name="use-header-bar">1</property>
+    <child internal-child="headerbar">
+      <object class="GtkHeaderBar" id="dialog-header-bar">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">10</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="dialog-action-area1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="jobs-close-button">
-                <property name="label" translatable="yes">Close</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
+        <property name="show_close_button">True</property>
         <child>
-          <object class="GtkBox" id="box2">
+          <object class="GtkButton" id="jobs-clear-all-button">
+            <property name="label" translatable="yes">Clear All</property>
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="hexpand">True</property>
-            <property name="vexpand">True</property>
-            <property name="orientation">vertical</property>
-            <child>
-              <object class="GtkScrolledWindow" id="queue-scrolledwindow">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkTreeView" id="job-treeview">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <child internal-child="selection">
-                      <object class="GtkTreeSelection" id="treeview-selection"/>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkToolbar" id="queue-toolbar">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_size">1</property>
-                <child>
-                  <object class="GtkToolButton" id="job-release-button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Resume Printing</property>
-                    <property name="use_underline">True</property>
-                    <property name="icon_name">media-playback-start-symbolic</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="homogeneous">True</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkToolButton" id="job-hold-button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Pause Printing</property>
-                    <property name="use_underline">True</property>
-                    <property name="icon_name">media-playback-pause-symbolic</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="homogeneous">True</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkToolButton" id="job-cancel-button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">Cancel Print Job</property>
-                    <property name="use_underline">True</property>
-                    <property name="icon_name">media-playback-stop-symbolic</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="homogeneous">True</property>
-                  </packing>
-                </child>
-                <style>
-                  <class name="inline-toolbar"/>
-                </style>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="use_underline">True</property>
+            <property name="valign">center</property>
+            <style>
+              <class name="destructive-action"/>
+            </style>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
         </child>
       </object>
     </child>
-    <action-widgets>
-      <action-widget response="0">jobs-close-button</action-widget>
-    </action-widgets>
+    <child internal-child="vbox">
+     <object class="GtkBox" id="dialog-vbox1">
+       <property name="can_focus">False</property>
+       <property name="orientation">vertical</property>
+       <property name="border_width">0</property>
+       <child>
+         <object class="GtkScrolledWindow" id="scrolledwindow">
+          <property name="visible">True</property>
+           <property name="can_focus">True</property>
+           <property name="vexpand">True</property>
+           <property name="hscrollbar-policy">never</property>
+           <property name="shadow_type">none</property>
+           <child>
+             <object class="GtkListBox" id="jobs-listbox">
+               <property name="visible">True</property>
+               <property name="can-focus">True</property>
+               <property name="halign">fill</property>
+               <property name="valign">fill</property>
+               <property name="selection-mode">none</property>
+               <child>
+                 <placeholder/>
+               </child>
+             </object>
+           </child>
+         </object>
+         <packing>
+           <property name="expand">False</property>
+           <property name="fill">True</property>
+           <property name="position">0</property>
+         </packing>
+        </child>
+      </object>
+    </child>
   </object>
 </interface>
diff --git a/panels/printers/pp-job.c b/panels/printers/pp-job.c
new file mode 100644
index 0000000..f66f6db
--- /dev/null
+++ b/panels/printers/pp-job.c
@@ -0,0 +1,138 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015  Red Hat, Inc,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges redhat com>
+ */
+
+#include "pp-job.h"
+
+enum
+{
+  PROP_ID = 1,
+  PROP_TITLE,
+  PROP_STATE,
+  PROP_TIME_STRING,
+  LAST_PROPERTY
+};
+
+struct _PpJob
+{
+  GObject parent;
+
+  gint   id;
+  gchar *title;
+  gint   state;
+  gchar *time_string;
+};
+
+static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
+
+G_DEFINE_TYPE (PpJob, pp_job, G_TYPE_OBJECT)
+
+static void
+pp_job_init (PpJob *obj)
+{
+}
+
+static void
+job_get_property (GObject    *object,
+                  guint       property_id,
+                  GValue     *value,
+                  GParamSpec *pspec)
+{
+  PpJob *obj = (PpJob *)object;
+
+  switch (property_id)
+  {
+    case PROP_ID:
+      g_value_set_int (value, obj->id);
+      break;
+    case PROP_TITLE:
+      g_value_set_string (value, obj->title);
+      break;
+    case PROP_STATE:
+      g_value_set_int (value, obj->state);
+      break;
+    case PROP_TIME_STRING:
+      g_value_set_string (value, obj->time_string);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+job_set_property (GObject      *object,
+                  guint         property_id,
+                  const GValue *value,
+                  GParamSpec   *pspec)
+{
+  PpJob *obj = (PpJob *)object;
+
+  switch (property_id)
+  {
+    case PROP_ID:
+      obj->id = g_value_get_int (value);
+      break;
+    case PROP_TITLE:
+      g_free (obj->title);
+      obj->title = g_value_dup_string (value);
+      break;
+    case PROP_STATE:
+      obj->state = g_value_get_int (value);
+      break;
+    case PROP_TIME_STRING:
+      g_free (obj->time_string);
+      obj->time_string = g_value_dup_string (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+  }
+}
+
+static void
+job_finalize (GObject *obj)
+{
+  PpJob *object = (PpJob *)obj;
+
+  g_free (object->title);
+  g_free (object->time_string);
+
+  G_OBJECT_CLASS (pp_job_parent_class)->finalize (obj);
+}
+
+static void
+pp_job_class_init (PpJobClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->get_property = job_get_property;
+  object_class->set_property = job_set_property;
+  object_class->finalize = job_finalize;
+
+  properties[PROP_ID] = g_param_spec_int ("id", "id", "id",
+                                          0, G_MAXINT, 0, G_PARAM_READWRITE);
+  properties[PROP_TITLE] = g_param_spec_string ("title", "title", "title",
+                                                NULL, G_PARAM_READWRITE);
+  properties[PROP_STATE] = g_param_spec_int ("state", "state", "state",
+                                             0, G_MAXINT, 0, G_PARAM_READWRITE);
+  properties[PROP_TIME_STRING] = g_param_spec_string ("time_string", "time_string", "time_string",
+                                                      NULL, G_PARAM_READWRITE);
+  g_object_class_install_properties (object_class, LAST_PROPERTY, properties);
+}
diff --git a/panels/printers/pp-job.h b/panels/printers/pp-job.h
new file mode 100644
index 0000000..13b4238
--- /dev/null
+++ b/panels/printers/pp-job.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2015  Red Hat, Inc,
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Felipe Borges <feborges redhat com>
+ */
+
+#ifndef __PP_JOB_H__
+#define __PP_JOB_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PpJob      PpJob;
+typedef struct _PpJobClass PpJobClass;
+
+struct _PpJobClass
+{
+  GObjectClass parent_class;
+};
+
+GType pp_job_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/panels/printers/pp-jobs-dialog.c b/panels/printers/pp-jobs-dialog.c
index 2d8682e..473e131 100644
--- a/panels/printers/pp-jobs-dialog.c
+++ b/panels/printers/pp-jobs-dialog.c
@@ -31,8 +31,10 @@
 
 #include <cups/cups.h>
 
+#include "shell/list-box-helper.h"
 #include "pp-jobs-dialog.h"
 #include "pp-utils.h"
+#include "pp-job.h"
 
 #define EMPTY_TEXT "\xe2\x80\x94"
 
@@ -46,6 +48,7 @@ struct _PpJobsDialog {
   GtkWidget  *parent;
 
   GtkWidget  *dialog;
+  GtkListBox *listbox;
 
   UserResponseCallback user_callback;
   gpointer             user_data;
@@ -54,38 +57,134 @@ struct _PpJobsDialog {
 
   cups_job_t *jobs;
   gint num_jobs;
-  gint current_job_id;
 
   gint ref_count;
 };
 
-enum
+static void
+job_process_cb_cb (gpointer user_data)
 {
-  JOB_ID_COLUMN,
-  JOB_TITLE_COLUMN,
-  JOB_STATE_COLUMN,
-  JOB_CREATION_TIME_COLUMN,
-  JOB_N_COLUMNS
-};
+}
+
+static void
+job_stop_cb (GtkButton *button,
+             gint       job_id)
+{
+  job_cancel_purge_async (job_id,
+                          FALSE,
+                          NULL,
+                          job_process_cb_cb,
+                          NULL);
+}
+
+static void
+job_pause_cb (GtkButton *button,
+              gpointer   user_data)
+{
+  PpJob *job = (PpJob *)user_data;
+  gint job_id, job_state;
+
+  g_object_get (job, "id", &job_id, NULL);
+  g_object_get (job, "state", &job_state, NULL);
+
+  job_set_hold_until_async (job_id,
+                            job_state == IPP_JOB_HELD ? "no-hold" : "indefinite",
+                            NULL,
+                            job_process_cb_cb,
+                            NULL);
+
+  gtk_button_set_image (button,
+                        gtk_image_new_from_icon_name (job_state == IPP_JOB_HELD ?
+                                                      "media-playback-pause-symbolic" : 
"media-playback-start-symbolic",
+                                                      GTK_ICON_SIZE_SMALL_TOOLBAR));
+}
+
+static GtkWidget *
+create_listbox_row (gpointer item,
+                    gpointer user_data)
+{
+  PpJob *job = (PpJob *)item;
+  GtkWidget *box, *widget;
+  gchar *time_string, *state_string;
+  gint *job_id, job_state = NULL;
+
+  g_object_get (job, "id", &job_id, NULL);
+  g_object_get (job, "state", &job_state, NULL);
+  g_object_get (job, "time_string", &time_string, NULL);
+
+  switch (job_state)
+  {
+    case IPP_JOB_PENDING:
+      /* Translators: Job's state (job is waiting to be printed) */
+      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", "Held"));
+      break;
+    case IPP_JOB_PROCESSING:
+      /* Translators: Job's state (job is currently printing) */
+      state_string = g_strdup (C_("print job", "Processing"));
+      break;
+    case IPP_JOB_STOPPED:
+      /* Translators: Job's state (job has been stopped) */
+      state_string = g_strdup (C_("print job", "Stopped"));
+      break;
+    case IPP_JOB_CANCELED:
+      /* Translators: Job's state (job has been canceled) */
+      state_string = g_strdup (C_("print job", "Canceled"));
+      break;
+    case IPP_JOB_ABORTED:
+      /* Translators: Job's state (job has aborted due to error) */
+      state_string = g_strdup (C_("print job", "Aborted"));
+      break;
+    case IPP_JOB_COMPLETED:
+      /* Translators: Job's state (job has completed successfully) */
+      state_string = g_strdup (C_("print job", "Completed"));
+      break;
+  }
+
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  g_object_set (box, "margin", 6, NULL);
+  gtk_widget_set_tooltip_text (box, time_string);
+  gtk_container_set_border_width (GTK_CONTAINER (box), 2);
+
+  widget = gtk_label_new ("");
+  g_object_bind_property (job, "title", widget, "label", G_BINDING_SYNC_CREATE);
+  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);
+  gtk_widget_set_halign (widget, GTK_ALIGN_END);
+  gtk_widget_set_margin_end (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_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 4);
+
+  widget = gtk_button_new_from_icon_name ("media-playback-stop-symbolic",
+                                          GTK_ICON_SIZE_SMALL_TOOLBAR);
+  g_signal_connect (widget, "clicked", G_CALLBACK (job_stop_cb), job_id);
+  gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 4);
+
+  gtk_widget_show_all (box);
+
+  return box;
+}
 
 static void
 update_jobs_list_cb (cups_job_t *jobs,
                      gint        num_of_jobs,
                      gpointer    user_data)
 {
-  GtkTreeSelection *selection;
   PpJobsDialog     *dialog = (PpJobsDialog *) user_data;
-  GtkListStore     *store;
-  GtkTreeView      *treeview;
-  GtkTreeIter       select_iter;
-  GtkTreeIter       iter;
+  GListStore       *store;
   GSettings        *settings;
-  gboolean          select_iter_set = FALSE;
   gint              i;
-  gint              select_index = 0;
 
-  treeview = (GtkTreeView*)
-    gtk_builder_get_object (dialog->builder, "job-treeview");
+  store = g_list_store_new (pp_job_get_type ());
 
   if (dialog->num_jobs > 0)
     cupsFreeJobs (dialog->num_jobs, dialog->jobs);
@@ -93,29 +192,14 @@ update_jobs_list_cb (cups_job_t *jobs,
   dialog->num_jobs = num_of_jobs;
   dialog->jobs = jobs;
 
-  store = gtk_list_store_new (JOB_N_COLUMNS,
-                              G_TYPE_INT,
-                              G_TYPE_STRING,
-                              G_TYPE_STRING,
-                              G_TYPE_STRING);
-
-  if (dialog->current_job_id >= 0)
-    {
-      for (i = 0; i < dialog->num_jobs; i++)
-        {
-          select_index = i;
-          if (dialog->jobs[i].id >= dialog->current_job_id)
-            break;
-        }
-    }
-
   for (i = 0; i < dialog->num_jobs; i++)
     {
       GDesktopClockFormat  value;
       GDateTime           *time;
-      struct tm *ts;
-      gchar     *time_string;
-      gchar     *state = NULL;
+      struct tm           *ts;
+      gchar               *time_string;
+      gchar               *state = NULL;
+      PpJob               *job;
 
       ts = localtime (&(dialog->jobs[i].creation_time));
       time = g_date_time_new_local (ts->tm_year + 1900,
@@ -135,66 +219,24 @@ update_jobs_list_cb (cups_job_t *jobs,
 
       g_date_time_unref (time);
 
-      switch (dialog->jobs[i].state)
-        {
-          case IPP_JOB_PENDING:
-            /* Translators: Job's state (job is waiting to be printed) */
-            state = g_strdup (C_("print job", "Pending"));
-            break;
-          case IPP_JOB_HELD:
-            /* Translators: Job's state (job is held for printing) */
-            state = g_strdup (C_("print job", "Held"));
-            break;
-          case IPP_JOB_PROCESSING:
-            /* Translators: Job's state (job is currently printing) */
-            state = g_strdup (C_("print job", "Processing"));
-            break;
-          case IPP_JOB_STOPPED:
-            /* Translators: Job's state (job has been stopped) */
-            state = g_strdup (C_("print job", "Stopped"));
-            break;
-          case IPP_JOB_CANCELED:
-            /* Translators: Job's state (job has been canceled) */
-            state = g_strdup (C_("print job", "Canceled"));
-            break;
-          case IPP_JOB_ABORTED:
-            /* Translators: Job's state (job has aborted due to error) */
-            state = g_strdup (C_("print job", "Aborted"));
-            break;
-          case IPP_JOB_COMPLETED:
-            /* Translators: Job's state (job has completed successfully) */
-            state = g_strdup (C_("print job", "Completed"));
-            break;
-        }
-
-      gtk_list_store_append (store, &iter);
-      gtk_list_store_set (store, &iter,
-                          JOB_ID_COLUMN, dialog->jobs[i].id,
-                          JOB_TITLE_COLUMN, dialog->jobs[i].title,
-                          JOB_STATE_COLUMN, state,
-                          JOB_CREATION_TIME_COLUMN, time_string,
-                          -1);
-
-      if (i == select_index)
-        {
-          select_iter = iter;
-          select_iter_set = TRUE;
-          dialog->current_job_id = dialog->jobs[i].id;
-        }
+      job = g_object_new (pp_job_get_type (),
+                          "id", dialog->jobs[i].id,
+                          "title", dialog->jobs[i].title,
+                          "state", dialog->jobs[i].state,
+                          "time_string", time_string,
+                          NULL);
+      g_list_store_append (store, job);
 
+      g_object_unref (job);
       g_free (time_string);
       g_free (state);
     }
 
-  gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
+  gtk_list_box_bind_model (dialog->listbox, G_LIST_MODEL (store),
+                           create_listbox_row, NULL, NULL);
 
-  if (select_iter_set &&
-      (selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview))))
-    {
-      gtk_tree_selection_select_iter (selection, &select_iter);
-    }
+  gtk_container_add (GTK_CONTAINER (dialog->listbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
 
-  g_object_unref (store);
   dialog->ref_count--;
 }
 
@@ -213,162 +255,6 @@ update_jobs_list (PpJobsDialog *dialog)
 }
 
 static void
-job_selection_changed_cb (GtkTreeSelection *selection,
-                          gpointer          user_data)
-{
-  PpJobsDialog *dialog = (PpJobsDialog *) user_data;
-  GtkTreeModel *model;
-  GtkTreeIter   iter;
-  GtkWidget    *widget;
-  gboolean      release_button_sensitive = FALSE;
-  gboolean      hold_button_sensitive = FALSE;
-  gboolean      cancel_button_sensitive = FALSE;
-  gint          id = -1;
-  gint          i;
-
-  if (gtk_tree_selection_get_selected (selection, &model, &iter))
-    {
-      gtk_tree_model_get (model, &iter,
-                          JOB_ID_COLUMN, &id,
-                          -1);
-    }
-  else
-    {
-      id = -1;
-    }
-
-  dialog->current_job_id = id;
-
-  if (dialog->current_job_id >= 0 &&
-      dialog->jobs != NULL)
-    {
-      for (i = 0; i < dialog->num_jobs; i++)
-        {
-          if (dialog->jobs[i].id == dialog->current_job_id)
-            {
-              ipp_jstate_t job_state = dialog->jobs[i].state;
-
-              release_button_sensitive = job_state == IPP_JOB_HELD;
-              hold_button_sensitive = job_state == IPP_JOB_PENDING;
-              cancel_button_sensitive = job_state < IPP_JOB_CANCELED;
-
-              break;
-            }
-        }
-    }
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-release-button");
-  gtk_widget_set_sensitive (widget, release_button_sensitive);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-hold-button");
-  gtk_widget_set_sensitive (widget, hold_button_sensitive);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-cancel-button");
-  gtk_widget_set_sensitive (widget, cancel_button_sensitive);
-}
-
-static void
-populate_jobs_list (PpJobsDialog *dialog)
-{
-  GtkTreeViewColumn *column;
-  GtkCellRenderer   *renderer;
-  GtkCellRenderer   *title_renderer;
-  GtkTreeView       *treeview;
-
-  treeview = (GtkTreeView*)
-    gtk_builder_get_object (dialog->builder, "job-treeview");
-
-  renderer = gtk_cell_renderer_text_new ();
-  title_renderer = gtk_cell_renderer_text_new ();
-
-  /* Translators: Name of column showing titles of print jobs */
-  column = gtk_tree_view_column_new_with_attributes (_("Job Title"), title_renderer,
-                                                     "text", JOB_TITLE_COLUMN, NULL);
-  g_object_set (G_OBJECT (title_renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-  gtk_tree_view_column_set_fixed_width (column, 180);
-  gtk_tree_view_column_set_min_width (column, 180);
-  gtk_tree_view_column_set_max_width (column, 180);
-  gtk_tree_view_append_column (treeview, column);
-
-  /* Translators: Name of column showing statuses of print jobs */
-  column = gtk_tree_view_column_new_with_attributes (_("Job State"), renderer,
-                                                     "text", JOB_STATE_COLUMN, NULL);
-  gtk_tree_view_column_set_expand (column, TRUE);
-  gtk_tree_view_append_column (treeview, column);
-
-  /* Translators: Name of column showing times of creation of print jobs */
-  column = gtk_tree_view_column_new_with_attributes (_("Time"), renderer,
-                                                     "text", JOB_CREATION_TIME_COLUMN, NULL);
-  gtk_tree_view_column_set_expand (column, TRUE);
-  gtk_tree_view_append_column (treeview, column);
-
-  g_signal_connect (gtk_tree_view_get_selection (treeview),
-                    "changed", G_CALLBACK (job_selection_changed_cb), dialog);
-
-  update_jobs_list (dialog);
-}
-
-static void
-job_process_cb_cb (gpointer user_data)
-{
-}
-
-static void
-job_process_cb (GtkButton *button,
-                gpointer   user_data)
-{
-  PpJobsDialog *dialog = (PpJobsDialog *) user_data;
-  GtkWidget    *widget;
-
-  if (dialog->current_job_id >= 0)
-    {
-      if ((GtkButton*) gtk_builder_get_object (dialog->builder,
-                                               "job-cancel-button") ==
-          button)
-        {
-          job_cancel_purge_async (dialog->current_job_id,
-                                  FALSE,
-                                  NULL,
-                                  job_process_cb_cb,
-                                  dialog);
-        }
-      else if ((GtkButton*) gtk_builder_get_object (dialog->builder,
-                                                    "job-hold-button") ==
-               button)
-        {
-          job_set_hold_until_async (dialog->current_job_id,
-                                    "indefinite",
-                                    NULL,
-                                    job_process_cb_cb,
-                                    dialog);
-        }
-      else
-        {
-          job_set_hold_until_async (dialog->current_job_id,
-                                    "no-hold",
-                                    NULL,
-                                    job_process_cb_cb,
-                                    dialog);
-        }
-  }
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-release-button");
-  gtk_widget_set_sensitive (widget, FALSE);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-hold-button");
-  gtk_widget_set_sensitive (widget, FALSE);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-cancel-button");
-  gtk_widget_set_sensitive (widget, FALSE);
-}
-
-static void
 jobs_dialog_response_cb (GtkDialog *dialog,
                          gint       response_id,
                          gpointer   user_data)
@@ -382,15 +268,28 @@ jobs_dialog_response_cb (GtkDialog *dialog,
                               jobs_dialog->user_data);
 }
 
+static void
+on_clear_all_button_clicked (GtkButton *button,
+                             gpointer   user_data)
+{
+  PpJobsDialog *dialog = (PpJobsDialog *) user_data;
+
+  job_cancel_purge_all_async (dialog->jobs,
+                              dialog->num_jobs,
+                              FALSE,
+                              NULL,
+                              job_process_cb_cb,
+                              NULL);
+}
+
 PpJobsDialog *
 pp_jobs_dialog_new (GtkWindow            *parent,
                     UserResponseCallback  user_callback,
                     gpointer              user_data,
                     gchar                *printer_name)
 {
-  GtkStyleContext *context;
   PpJobsDialog    *dialog;
-  GtkWidget       *widget;
+  GtkButton       *clear_all_button;
   GError          *error = NULL;
   gchar           *objects[] = { "jobs-dialog", NULL };
   guint            builder_result;
@@ -416,43 +315,25 @@ pp_jobs_dialog_new (GtkWindow            *parent,
   dialog->user_callback = user_callback;
   dialog->user_data = user_data;
   dialog->printer_name = g_strdup (printer_name);
-  dialog->current_job_id = -1;
   dialog->ref_count = 0;
 
   /* 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);
 
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-cancel-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), dialog);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-hold-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), dialog);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "job-release-button");
-  g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), dialog);
-
+  clear_all_button = (GtkButton *) 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);
 
-  /* Set junctions */
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "queue-scrolledwindow");
-  context = gtk_widget_get_style_context (widget);
-  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
-
-  widget = (GtkWidget*)
-    gtk_builder_get_object (dialog->builder, "queue-toolbar");
-  context = gtk_widget_get_style_context (widget);
-  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-
-
-  title = g_strdup_printf (_("%s Active Jobs"), printer_name);
+  title = g_strdup_printf (_("%s - Active Jobs"), printer_name);
   gtk_window_set_title (GTK_WINDOW (dialog->dialog), title);
   g_free (title);
 
-  populate_jobs_list (dialog);
+  dialog->listbox = (GtkListBox*)
+        gtk_builder_get_object (dialog->builder, "jobs-listbox");
+  gtk_list_box_set_header_func (dialog->listbox,
+                                cc_list_box_update_header_func, NULL, NULL);
+
+  update_jobs_list (dialog);
 
   gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), GTK_WINDOW (parent));
   gtk_window_present (GTK_WINDOW (dialog->dialog));
diff --git a/panels/printers/pp-utils.c b/panels/printers/pp-utils.c
index 899bcf3..c806ea0 100644
--- a/panels/printers/pp-utils.c
+++ b/panels/printers/pp-utils.c
@@ -3864,6 +3864,26 @@ job_cancel_purge_async_dbus_cb (GObject      *source_object,
 }
 
 void
+job_cancel_purge_all_async (cups_job_t   *jobs,
+                            gint          num_of_jobs,
+                            gboolean      job_purge,
+                            GCancellable *cancellable,
+                            JCPCallback   callback,
+                            gpointer      user_data)
+{
+  gint i;
+
+  for (i = 0; i < num_of_jobs; i++)
+   {
+     job_cancel_purge_async (jobs[i].id,
+                             job_purge,
+                             cancellable,
+                             callback,
+                             user_data);
+   }
+}
+
+void
 job_cancel_purge_async (gint          job_id,
                         gboolean      job_purge,
                         GCancellable *cancellable,
diff --git a/panels/printers/pp-utils.h b/panels/printers/pp-utils.h
index 9b39b6d..c9e3fda 100644
--- a/panels/printers/pp-utils.h
+++ b/panels/printers/pp-utils.h
@@ -267,6 +267,13 @@ void job_cancel_purge_async (gint          job_id,
                              JCPCallback   callback,
                              gpointer      user_data);
 
+void job_cancel_purge_all_async (cups_job_t   *jobs,
+                                 gint          num_of_jobs,
+                                 gboolean      job_purge,
+                                 GCancellable *cancellable,
+                                 JCPCallback   callback,
+                                 gpointer      user_data);
+
 typedef void (*JSHUCallback) (gpointer user_data);
 
 void job_set_hold_until_async (gint          job_id,


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