[gnome-control-center] printers: Place jobs to separate dialog
- From: Marek KaÅÃk <mkasik src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] printers: Place jobs to separate dialog
- Date: Tue, 7 Aug 2012 12:11:35 +0000 (UTC)
commit c6d8b9c8252cbf4e439cad0a225b841b2189fec0
Author: Marek Kasik <mkasik redhat com>
Date: Tue Aug 7 14:09:33 2012 +0200
printers: Place jobs to separate dialog
This commit places list of jobs to separate dialog. The dialog
is updated through calling of pp_jobs_dialog_update()
from "Printers" panel because the panel is already subscribed
to cups notifications.
panels/printers/Makefile.am | 7 +-
panels/printers/cc-printers-panel.c | 446 ++++-------------------------
panels/printers/jobs-dialog.ui | 183 ++++++++++++
panels/printers/pp-jobs-dialog.c | 541 +++++++++++++++++++++++++++++++++++
panels/printers/pp-jobs-dialog.h | 42 +++
panels/printers/pp-utils.c | 265 +++++++++++++++++
panels/printers/pp-utils.h | 26 ++
panels/printers/printers.ui | 154 +----------
8 files changed, 1122 insertions(+), 542 deletions(-)
---
diff --git a/panels/printers/Makefile.am b/panels/printers/Makefile.am
index 249ce69..0fb0c60 100644
--- a/panels/printers/Makefile.am
+++ b/panels/printers/Makefile.am
@@ -5,6 +5,7 @@ dist_ui_DATA = \
new-printer-dialog.ui \
ppd-selection-dialog.ui \
options-dialog.ui \
+ jobs-dialog.ui \
printers.ui
INCLUDES = \
@@ -31,8 +32,10 @@ libprinters_la_SOURCES = \
pp-new-printer-dialog.h \
pp-ppd-selection-dialog.c \
pp-ppd-selection-dialog.h \
- pp-options-dialog.c \
- pp-options-dialog.h \
+ pp-options-dialog.c \
+ pp-options-dialog.h \
+ pp-jobs-dialog.c \
+ pp-jobs-dialog.h \
cc-printers-panel.c \
cc-printers-panel.h
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
index 88cccff..436e3ee 100644
--- a/panels/printers/cc-printers-panel.c
+++ b/panels/printers/cc-printers-panel.c
@@ -35,6 +35,7 @@
#include "pp-new-printer-dialog.h"
#include "pp-ppd-selection-dialog.h"
#include "pp-options-dialog.h"
+#include "pp-jobs-dialog.h"
#include "pp-utils.h"
G_DEFINE_DYNAMIC_TYPE (CcPrintersPanel, cc_printers_panel, CC_TYPE_PANEL)
@@ -42,15 +43,10 @@ G_DEFINE_DYNAMIC_TYPE (CcPrintersPanel, cc_printers_panel, CC_TYPE_PANEL)
#define PRINTERS_PANEL_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_PRINTERS_PANEL, CcPrintersPanelPrivate))
-#define MECHANISM_BUS "org.opensuse.CupsPkHelper.Mechanism"
-
#define SUPPLY_BAR_HEIGHT 20
#define EMPTY_TEXT "\xe2\x80\x94"
-#define CLOCK_SCHEMA "org.gnome.desktop.interface"
-#define CLOCK_FORMAT_KEY "clock-format"
-
#define RENEW_INTERVAL 500
#define SUBSCRIPTION_DURATION 600
@@ -70,9 +66,7 @@ struct _CcPrintersPanelPrivate
int num_dests;
int current_dest;
- cups_job_t *jobs;
int num_jobs;
- int current_job;
GdkRGBA background_color;
@@ -80,9 +74,10 @@ struct _CcPrintersPanelPrivate
GSettings *lockdown_settings;
- PpNewPrinterDialog *pp_new_printer_dialog;
+ PpNewPrinterDialog *pp_new_printer_dialog;
PpPPDSelectionDialog *pp_ppd_selection_dialog;
- PpOptionsDialog *pp_options_dialog;
+ PpOptionsDialog *pp_options_dialog;
+ PpJobsDialog *pp_jobs_dialog;
GDBusProxy *cups_proxy;
GDBusConnection *cups_bus_connection;
@@ -108,7 +103,7 @@ typedef struct
GCancellable *cancellable;
} SetPPDItem;
-static void actualize_jobs_list (CcPrintersPanel *self);
+static void update_jobs_count (CcPrintersPanel *self);
static void actualize_printers_list (CcPrintersPanel *self);
static void update_sensitivity (gpointer user_data);
static void printer_disable_cb (GObject *gobject, GParamSpec *pspec, gpointer user_data);
@@ -155,12 +150,6 @@ cc_printers_panel_dispose (GObject *object)
free_dests (CC_PRINTERS_PANEL (object));
- if (priv->num_jobs > 0)
- cupsFreeJobs (priv->num_jobs, priv->jobs);
- priv->jobs = NULL;
- priv->num_jobs = 0;
- priv->current_job = -1;
-
if (priv->builder)
{
g_object_unref (priv->builder);
@@ -375,7 +364,7 @@ on_cups_notification (GDBusConnection *connection,
priv->dests != NULL &&
g_strcmp0 (g_strrstr (attr_printer_uri->values[0].string.text, "/") + 1,
priv->dests[priv->current_dest].name) == 0)
- actualize_jobs_list (self);
+ update_jobs_count (self);
}
ippDelete(response);
}
@@ -517,7 +506,6 @@ free_dests (CcPrintersPanel *self)
enum
{
NOTEBOOK_INFO_PAGE = 0,
- NOTEBOOK_JOBS_PAGE,
NOTEBOOK_OPTIONS_PAGE,
NOTEBOOK_NO_PRINTERS_PAGE,
NOTEBOOK_NO_CUPS_PAGE,
@@ -556,14 +544,12 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
gchar *printer_name = NULL;
gchar *printer_icon = NULL;
gchar *printer_type = NULL;
- gchar *active_jobs = NULL;
gchar *supply_type = NULL;
gchar *printer_uri = NULL;
gchar *location = NULL;
gchar *status = NULL;
gchar *device_uri = NULL;
gchar *printer_hostname = NULL;
- guint num_jobs;
int printer_state = 3;
int id = -1;
int i, j;
@@ -639,29 +625,7 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
priv->current_dest = id;
- if (!(priv->current_dest >= 0 &&
- priv->current_dest < priv->num_dests &&
- priv->dests != NULL &&
- priv->current_job >= 0 &&
- priv->current_job < priv->num_jobs &&
- priv->jobs != NULL &&
- g_strcmp0 (priv->dests[priv->current_dest].name,
- priv->jobs[priv->current_job].dest) == 0))
- {
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-release-button");
- gtk_widget_set_sensitive (widget, FALSE);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-hold-button");
- gtk_widget_set_sensitive (widget, FALSE);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-cancel-button");
- gtk_widget_set_sensitive (widget, FALSE);
-
- actualize_jobs_list (self);
- }
+ update_jobs_count (self);
if (priv->current_dest >= 0 &&
priv->current_dest < priv->num_dests &&
@@ -936,21 +900,6 @@ printer_selection_changed_cb (GtkTreeSelection *selection,
}
else
gtk_label_set_text (GTK_LABEL (widget), EMPTY_TEXT);
-
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "printer-jobs-label");
- num_jobs = priv->num_jobs < 0 ? 0 : (guint) priv->num_jobs;
- /* Translators: there is n active print jobs on this printer */
- active_jobs = g_strdup_printf (ngettext ("%u active", "%u active", num_jobs), num_jobs);
-
- if (active_jobs)
- {
- cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), active_jobs);
- g_free (active_jobs);
- }
- else
- cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
}
else
{
@@ -1307,319 +1256,49 @@ enum
};
static void
-actualize_jobs_list (CcPrintersPanel *self)
+update_jobs_count (CcPrintersPanel *self)
{
CcPrintersPanelPrivate *priv;
- GtkListStore *store;
- GtkTreeView *treeview;
- GtkTreeIter iter;
- GSettings *settings;
+ cups_job_t *jobs;
GtkWidget *widget;
- gchar *active_jobs;
+ gchar *active_jobs = NULL;
gint num_jobs;
- gint i;
priv = PRINTERS_PANEL_PRIVATE (self);
- treeview = (GtkTreeView*)
- gtk_builder_get_object (priv->builder, "job-treeview");
-
- if (priv->num_jobs > 0)
- cupsFreeJobs (priv->num_jobs, priv->jobs);
priv->num_jobs = -1;
- priv->jobs = NULL;
- priv->current_job = -1;
if (priv->current_dest >= 0 &&
priv->current_dest < priv->num_dests &&
priv->dests != NULL)
{
- priv->num_jobs = cupsGetJobs (&priv->jobs, priv->dests[priv->current_dest].name, 1, CUPS_WHICHJOBS_ACTIVE);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "printer-jobs-label");
+ priv->num_jobs = cupsGetJobs (&jobs, priv->dests[priv->current_dest].name, 1, CUPS_WHICHJOBS_ACTIVE);
+ if (priv->num_jobs > 0)
+ cupsFreeJobs (priv->num_jobs, jobs);
num_jobs = priv->num_jobs < 0 ? 0 : (guint) priv->num_jobs;
/* Translators: there is n active print jobs on this printer */
active_jobs = g_strdup_printf (ngettext ("%u active", "%u active", num_jobs), num_jobs);
-
- if (active_jobs)
- {
- cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), active_jobs);
- g_free (active_jobs);
- }
- else
- cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
}
- store = gtk_list_store_new (JOB_N_COLUMNS, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+ widget = (GtkWidget*)
+ gtk_builder_get_object (priv->builder, "printer-jobs-label");
- for (i = 0; i < priv->num_jobs; i++)
+ if (active_jobs)
{
- GDesktopClockFormat value;
- GDateTime *time;
- struct tm *ts;
- gchar *time_string;
- gchar *state = NULL;
-
- ts = localtime (&(priv->jobs[i].creation_time));
- time = g_date_time_new_local (ts->tm_year,
- ts->tm_mon,
- ts->tm_mday,
- ts->tm_hour,
- ts->tm_min,
- ts->tm_sec);
-
- settings = g_settings_new (CLOCK_SCHEMA);
- value = g_settings_get_enum (settings, CLOCK_FORMAT_KEY);
-
- if (value == G_DESKTOP_CLOCK_FORMAT_24H)
- time_string = g_date_time_format (time, "%k:%M");
- else
- time_string = g_date_time_format (time, "%l:%M %p");
-
- g_date_time_unref (time);
-
- switch (priv->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, i,
- JOB_TITLE_COLUMN, priv->jobs[i].title,
- JOB_STATE_COLUMN, state,
- JOB_CREATION_TIME_COLUMN, time_string,
- -1);
-
- g_free (time_string);
- g_free (state);
+ cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), active_jobs);
+ g_free (active_jobs);
}
-
- gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
- g_object_unref (store);
-}
-
-static void
-job_selection_changed_cb (GtkTreeSelection *selection,
- gpointer user_data)
-{
- CcPrintersPanelPrivate *priv;
- CcPrintersPanel *self = (CcPrintersPanel*) user_data;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkWidget *widget;
- int id = -1;
-
- priv = PRINTERS_PANEL_PRIVATE (self);
-
- if (gtk_tree_selection_get_selected (selection, &model, &iter))
- gtk_tree_model_get (model, &iter,
- JOB_ID_COLUMN, &id,
- -1);
else
- id = -1;
-
- priv->current_job = id;
+ cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT);
- if (priv->current_job >= 0 &&
- priv->current_job < priv->num_jobs &&
- priv->jobs != NULL)
+ if (priv->pp_jobs_dialog)
{
- ipp_jstate_t job_state = priv->jobs[priv->current_job].state;
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-release-button");
- gtk_widget_set_sensitive (widget, job_state == IPP_JOB_HELD);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-hold-button");
- gtk_widget_set_sensitive (widget, job_state == IPP_JOB_PENDING);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-cancel-button");
- gtk_widget_set_sensitive (widget, job_state < IPP_JOB_CANCELED);
+ pp_jobs_dialog_update (priv->pp_jobs_dialog);
}
}
static void
-populate_jobs_list (CcPrintersPanel *self)
-{
- CcPrintersPanelPrivate *priv;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- GtkCellRenderer *title_renderer;
- GtkTreeView *treeview;
-
- priv = PRINTERS_PANEL_PRIVATE (self);
-
- treeview = (GtkTreeView*)
- gtk_builder_get_object (priv->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), self);
-
- actualize_jobs_list (self);
-}
-
-static void
-job_process_cb (GtkButton *button,
- gpointer user_data)
-{
- CcPrintersPanelPrivate *priv;
- CcPrintersPanel *self = (CcPrintersPanel*) user_data;
- GDBusConnection *bus;
- GtkWidget *widget;
- GError *error = NULL;
- GVariant *output = NULL;
- int id = -1;
-
- priv = PRINTERS_PANEL_PRIVATE (self);
-
- if (priv->current_job >= 0 &&
- priv->current_job < priv->num_jobs &&
- priv->jobs != NULL)
- id = priv->jobs[priv->current_job].id;
-
- if (id >= 0)
- {
- bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
- if (!bus)
- {
- g_warning ("Failed to get system bus: %s", error->message);
- g_error_free (error);
- return;
- }
-
- if ((GtkButton*) gtk_builder_get_object (priv->builder,
- "job-cancel-button") ==
- button)
- output = g_dbus_connection_call_sync (bus,
- MECHANISM_BUS,
- "/",
- MECHANISM_BUS,
- "JobCancelPurge",
- g_variant_new ("(ib)", id, FALSE),
- G_VARIANT_TYPE ("(s)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- else if ((GtkButton*) gtk_builder_get_object (priv->builder,
- "job-hold-button") ==
- button)
- output = g_dbus_connection_call_sync (bus,
- MECHANISM_BUS,
- "/",
- MECHANISM_BUS,
- "JobSetHoldUntil",
- g_variant_new ("(is)", id, "indefinite"),
- G_VARIANT_TYPE ("(s)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- else if ((GtkButton*) gtk_builder_get_object (priv->builder,
- "job-release-button") ==
- button)
- output = g_dbus_connection_call_sync (bus,
- MECHANISM_BUS,
- "/",
- MECHANISM_BUS,
- "JobSetHoldUntil",
- g_variant_new ("(is)", id, "no-hold"),
- G_VARIANT_TYPE ("(s)"),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- g_object_unref (bus);
-
- if (output)
- {
- const gchar *ret_error;
-
- g_variant_get (output, "(&s)", &ret_error);
- if (ret_error[0] != '\0')
- g_warning ("%s", ret_error);
- else
- actualize_jobs_list (self);
-
- g_variant_unref (output);
- }
- else
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
- }
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-release-button");
- gtk_widget_set_sensitive (widget, FALSE);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-hold-button");
- gtk_widget_set_sensitive (widget, FALSE);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-cancel-button");
- gtk_widget_set_sensitive (widget, FALSE);
-}
-
-static void
printer_disable_cb (GObject *gobject,
GParamSpec *pspec,
gpointer user_data)
@@ -2784,21 +2463,6 @@ go_back_cb (GtkButton *button,
}
static void
-switch_to_jobs_cb (GtkButton *button,
- gpointer user_data)
-{
- CcPrintersPanelPrivate *priv;
- CcPrintersPanel *self = (CcPrintersPanel*) user_data;
- GtkWidget *widget;
-
- priv = PRINTERS_PANEL_PRIVATE (self);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "notebook");
- gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), NOTEBOOK_JOBS_PAGE);
-}
-
-static void
printer_options_response_cb (GtkDialog *dialog,
gint response_id,
gpointer user_data)
@@ -2925,6 +2589,43 @@ update_label_padding (GtkWidget *widget,
}
static void
+jobs_dialog_response_cb (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ CcPrintersPanelPrivate *priv;
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+
+ priv = PRINTERS_PANEL_PRIVATE (self);
+
+ pp_jobs_dialog_free (priv->pp_jobs_dialog);
+ priv->pp_jobs_dialog = NULL;
+}
+
+static void
+printer_jobs_cb (GtkToolButton *toolbutton,
+ gpointer user_data)
+{
+ CcPrintersPanelPrivate *priv;
+ CcPrintersPanel *self = (CcPrintersPanel*) user_data;
+ GtkWidget *widget;
+
+ priv = PRINTERS_PANEL_PRIVATE (self);
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (priv->builder, "main-vbox");
+
+ if (priv->current_dest >= 0 &&
+ priv->current_dest < priv->num_dests &&
+ priv->dests != NULL)
+ priv->pp_jobs_dialog = pp_jobs_dialog_new (
+ GTK_WINDOW (gtk_widget_get_toplevel (widget)),
+ jobs_dialog_response_cb,
+ self,
+ priv->dests[priv->current_dest].name);
+}
+
+static void
cc_printers_panel_init (CcPrintersPanel *self)
{
CcPrintersPanelPrivate *priv;
@@ -2946,9 +2647,7 @@ cc_printers_panel_init (CcPrintersPanel *self)
priv->num_dests = 0;
priv->current_dest = -1;
- priv->jobs = NULL;
priv->num_jobs = 0;
- priv->current_job = -1;
priv->pp_new_printer_dialog = NULL;
priv->pp_options_dialog = NULL;
@@ -2988,18 +2687,6 @@ cc_printers_panel_init (CcPrintersPanel *self)
/* connect signals */
widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-cancel-button");
- g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), self);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-hold-button");
- g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), self);
-
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "job-release-button");
- g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), self);
-
- widget = (GtkWidget*)
gtk_builder_get_object (priv->builder, "printer-add-button");
g_signal_connect (widget, "clicked", G_CALLBACK (printer_add_cb), self);
@@ -3028,16 +2715,12 @@ cc_printers_panel_init (CcPrintersPanel *self)
g_signal_connect (widget, "clicked", G_CALLBACK (test_page_cb), self);
widget = (GtkWidget*)
- gtk_builder_get_object (priv->builder, "back-button-1");
- g_signal_connect (widget, "clicked", G_CALLBACK (go_back_cb), self);
-
- widget = (GtkWidget*)
gtk_builder_get_object (priv->builder, "back-button-2");
g_signal_connect (widget, "clicked", G_CALLBACK (go_back_cb), self);
widget = (GtkWidget*)
gtk_builder_get_object (priv->builder, "printer-jobs-button");
- g_signal_connect (widget, "clicked", G_CALLBACK (switch_to_jobs_cb), self);
+ g_signal_connect (widget, "clicked", G_CALLBACK (printer_jobs_cb), self);
widget = (GtkWidget*)
gtk_builder_get_object (priv->builder, "printer-options-button");
@@ -3075,16 +2758,6 @@ cc_printers_panel_init (CcPrintersPanel *self)
context = gtk_widget_get_style_context (widget);
gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
- widget = (GtkWidget*)
- gtk_builder_get_object (priv->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 (priv->builder, "queue-toolbar");
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-
/* Make model label and ip-address label selectable */
widget = (GtkWidget*)
@@ -3111,7 +2784,6 @@ Please check your installation");
&priv->background_color);
populate_printers_list (self);
- populate_jobs_list (self);
attach_to_cups_notifier (self);
priv->get_all_ppds_cancellable = g_cancellable_new ();
diff --git a/panels/printers/jobs-dialog.ui b/panels/printers/jobs-dialog.ui
new file mode 100644
index 0000000..d58be2c
--- /dev/null
+++ b/panels/printers/jobs-dialog.ui
@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkDialog" id="jobs-dialog">
+ <property name="width_request">500</property>
+ <property name="height_request">350</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes"> </property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="resizable">False</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="main-vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</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="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</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>
+ <child>
+ <object class="GtkAlignment" id="content-alignment">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="jobs-title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes" comments="Translators: This tab contains list of active print jobs of the selected printer">Active Jobs</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</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="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">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="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">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="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</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">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">jobs-close-button</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1"/>
+</interface>
diff --git a/panels/printers/pp-jobs-dialog.c b/panels/printers/pp-jobs-dialog.c
new file mode 100644
index 0000000..eac73f6
--- /dev/null
+++ b/panels/printers/pp-jobs-dialog.c
@@ -0,0 +1,541 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 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 3 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Marek Kasik <mkasik redhat com>
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include <gdesktop-enums.h>
+
+#include <cups/cups.h>
+
+#include "pp-jobs-dialog.h"
+#include "pp-utils.h"
+
+#define EMPTY_TEXT "\xe2\x80\x94"
+
+#define CLOCK_SCHEMA "org.gnome.desktop.interface"
+#define CLOCK_FORMAT_KEY "clock-format"
+
+static void pp_jobs_dialog_hide (PpJobsDialog *dialog);
+
+struct _PpJobsDialog {
+ GtkBuilder *builder;
+ GtkWidget *parent;
+
+ GtkWidget *dialog;
+
+ UserResponseCallback user_callback;
+ gpointer user_data;
+
+ gchar *printer_name;
+
+ cups_job_t *jobs;
+ gint num_jobs;
+ gint current_job_id;
+
+ gint ref_count;
+};
+
+enum
+{
+ JOB_ID_COLUMN,
+ JOB_TITLE_COLUMN,
+ JOB_STATE_COLUMN,
+ JOB_CREATION_TIME_COLUMN,
+ JOB_N_COLUMNS
+};
+
+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;
+ GSettings *settings;
+ gboolean select_iter_set = FALSE;
+ gint i;
+ gint select_index = 0;
+
+ treeview = (GtkTreeView*)
+ gtk_builder_get_object (dialog->builder, "job-treeview");
+
+ if (dialog->num_jobs > 0)
+ cupsFreeJobs (dialog->num_jobs, dialog->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;
+
+ ts = localtime (&(dialog->jobs[i].creation_time));
+ time = g_date_time_new_local (ts->tm_year,
+ ts->tm_mon,
+ ts->tm_mday,
+ ts->tm_hour,
+ ts->tm_min,
+ ts->tm_sec);
+
+ settings = g_settings_new (CLOCK_SCHEMA);
+ value = g_settings_get_enum (settings, CLOCK_FORMAT_KEY);
+
+ if (value == G_DESKTOP_CLOCK_FORMAT_24H)
+ time_string = g_date_time_format (time, "%k:%M");
+ else
+ time_string = g_date_time_format (time, "%l:%M %p");
+
+ 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;
+ }
+
+ g_free (time_string);
+ g_free (state);
+ }
+
+ gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
+
+ if (select_iter_set &&
+ (selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview))))
+ {
+ gtk_tree_selection_select_iter (selection, &select_iter);
+ }
+
+ g_object_unref (store);
+ dialog->ref_count--;
+}
+
+static void
+update_jobs_list (PpJobsDialog *dialog)
+{
+ if (dialog->printer_name)
+ {
+ dialog->ref_count++;
+ cups_get_jobs_async (dialog->printer_name,
+ TRUE,
+ CUPS_WHICHJOBS_ACTIVE,
+ update_jobs_list_cb,
+ 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)
+{
+ PpJobsDialog *jobs_dialog = (PpJobsDialog*) user_data;
+
+ pp_jobs_dialog_hide (jobs_dialog);
+
+ jobs_dialog->user_callback (GTK_DIALOG (jobs_dialog->dialog),
+ response_id,
+ jobs_dialog->user_data);
+}
+
+static void
+update_alignment_padding (GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer user_data)
+{
+ GtkAllocation allocation2;
+ PpJobsDialog *dialog = (PpJobsDialog*) user_data;
+ GtkWidget *action_area;
+ gint offset_left, offset_right;
+ guint padding_left, padding_right,
+ padding_top, padding_bottom;
+
+ action_area = (GtkWidget*)
+ gtk_builder_get_object (dialog->builder, "dialog-action-area1");
+ gtk_widget_get_allocation (action_area, &allocation2);
+
+ offset_left = allocation2.x - allocation->x;
+ offset_right = (allocation->x + allocation->width) -
+ (allocation2.x + allocation2.width);
+
+ gtk_alignment_get_padding (GTK_ALIGNMENT (widget),
+ &padding_top, &padding_bottom,
+ &padding_left, &padding_right);
+ if (allocation->x >= 0 && allocation2.x >= 0)
+ {
+ if (offset_left > 0 && offset_left != padding_left)
+ gtk_alignment_set_padding (GTK_ALIGNMENT (widget),
+ padding_top, padding_bottom,
+ offset_left, padding_right);
+
+ gtk_alignment_get_padding (GTK_ALIGNMENT (widget),
+ &padding_top, &padding_bottom,
+ &padding_left, &padding_right);
+ if (offset_right > 0 && offset_right != padding_right)
+ gtk_alignment_set_padding (GTK_ALIGNMENT (widget),
+ padding_top, padding_bottom,
+ padding_left, offset_right);
+ }
+}
+
+PpJobsDialog *
+pp_jobs_dialog_new (GtkWindow *parent,
+ UserResponseCallback user_callback,
+ gpointer user_data,
+ gchar *printer_name)
+{
+ PpJobsDialog *dialog;
+ GtkWidget *widget;
+ GError *error = NULL;
+ gchar *objects[] = { "jobs-dialog", NULL };
+ guint builder_result;
+ gchar *title;
+
+ dialog = g_new0 (PpJobsDialog, 1);
+
+ dialog->builder = gtk_builder_new ();
+ dialog->parent = GTK_WIDGET (parent);
+
+ builder_result = gtk_builder_add_objects_from_file (dialog->builder,
+ DATADIR"/jobs-dialog.ui",
+ objects, &error);
+
+ if (builder_result == 0)
+ {
+ g_warning ("Could not load ui: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ dialog->dialog = (GtkWidget *) gtk_builder_get_object (dialog->builder, "jobs-dialog");
+ 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, "content-alignment");
+ g_signal_connect (widget, "size-allocate", G_CALLBACK (update_alignment_padding), 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);
+
+ widget = (GtkWidget*)
+ gtk_builder_get_object (dialog->builder, "jobs-title");
+ title = g_strdup_printf (_("%s Active Jobs"), printer_name);
+ gtk_label_set_label (GTK_LABEL (widget), title);
+ g_free (title);
+
+ populate_jobs_list (dialog);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), GTK_WINDOW (parent));
+ gtk_window_present (GTK_WINDOW (dialog->dialog));
+ gtk_widget_show_all (GTK_WIDGET (dialog->dialog));
+
+ return dialog;
+}
+
+void
+pp_jobs_dialog_update (PpJobsDialog *dialog)
+{
+ update_jobs_list (dialog);
+}
+
+static gboolean
+pp_jobs_dialog_free_idle (gpointer user_data)
+{
+ PpJobsDialog *dialog = (PpJobsDialog*) user_data;
+
+ if (dialog->ref_count == 0)
+ {
+ gtk_widget_destroy (GTK_WIDGET (dialog->dialog));
+ dialog->dialog = NULL;
+
+ g_object_unref (dialog->builder);
+ dialog->builder = NULL;
+
+ if (dialog->num_jobs > 0)
+ cupsFreeJobs (dialog->num_jobs, dialog->jobs);
+
+ g_free (dialog->printer_name);
+
+ g_free (dialog);
+
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+void
+pp_jobs_dialog_free (PpJobsDialog *dialog)
+{
+ g_idle_add (pp_jobs_dialog_free_idle, dialog);
+}
+
+static void
+pp_jobs_dialog_hide (PpJobsDialog *dialog)
+{
+ gtk_widget_hide (GTK_WIDGET (dialog->dialog));
+}
diff --git a/panels/printers/pp-jobs-dialog.h b/panels/printers/pp-jobs-dialog.h
new file mode 100644
index 0000000..72ae66b
--- /dev/null
+++ b/panels/printers/pp-jobs-dialog.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright 2012 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 3 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Marek Kasik <mkasik redhat com>
+ */
+
+#ifndef __PP_JOBS_DIALOG_H__
+#define __PP_JOBS_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PpJobsDialog PpJobsDialog;
+
+typedef void (*UserResponseCallback) (GtkDialog *dialog, gint response_id, gpointer user_data);
+
+PpJobsDialog *pp_jobs_dialog_new (GtkWindow *parent,
+ UserResponseCallback user_callback,
+ gpointer user_data,
+ gchar *printer_name);
+void pp_jobs_dialog_update (PpJobsDialog *dialog);
+void pp_jobs_dialog_free (PpJobsDialog *dialog);
+
+G_END_DECLS
+
+#endif
diff --git a/panels/printers/pp-utils.c b/panels/printers/pp-utils.c
index 599bd1a..b53c0bd 100644
--- a/panels/printers/pp-utils.c
+++ b/panels/printers/pp-utils.c
@@ -4551,3 +4551,268 @@ printer_add_option_async (const gchar *printer_name,
printer_add_option_async_dbus_cb,
data);
}
+
+typedef struct
+{
+ gchar *printer_name;
+ gboolean my_jobs;
+ gint which_jobs;
+ cups_job_t *jobs;
+ gint num_of_jobs;
+ CGJCallback callback;
+ gpointer user_data;
+ GMainContext *context;
+} CGJData;
+
+static gboolean
+cups_get_jobs_idle_cb (gpointer user_data)
+{
+ CGJData *data = (CGJData *) user_data;
+
+ data->callback (data->jobs,
+ data->num_of_jobs,
+ data->user_data);
+
+ return FALSE;
+}
+
+static void
+cups_get_jobs_data_free (gpointer user_data)
+{
+ CGJData *data = (CGJData *) user_data;
+
+ if (data->context)
+ g_main_context_unref (data->context);
+ g_free (data->printer_name);
+ g_free (data);
+}
+
+static void
+cups_get_jobs_cb (gpointer user_data)
+{
+ CGJData *data = (CGJData *) user_data;
+ GSource *idle_source;
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source,
+ cups_get_jobs_idle_cb,
+ data,
+ cups_get_jobs_data_free);
+ g_source_attach (idle_source, data->context);
+ g_source_unref (idle_source);
+}
+
+static gpointer
+cups_get_jobs_func (gpointer user_data)
+{
+ CGJData *data = (CGJData *) user_data;
+
+ data->num_of_jobs = cupsGetJobs (&data->jobs,
+ data->printer_name,
+ data->my_jobs ? 1 : 0,
+ data->which_jobs);
+
+ cups_get_jobs_cb (data);
+
+ return NULL;
+}
+
+void
+cups_get_jobs_async (const gchar *printer_name,
+ gboolean my_jobs,
+ gint which_jobs,
+ CGJCallback callback,
+ gpointer user_data)
+{
+ CGJData *data;
+ GThread *thread;
+ GError *error = NULL;
+
+ data = g_new0 (CGJData, 1);
+ data->printer_name = g_strdup (printer_name);
+ data->my_jobs = my_jobs;
+ data->which_jobs = which_jobs;
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = g_main_context_ref_thread_default ();
+
+ thread = g_thread_try_new ("cups-get-jobs",
+ cups_get_jobs_func,
+ data,
+ &error);
+
+ if (!thread)
+ {
+ g_warning ("%s", error->message);
+ callback (NULL, 0, user_data);
+
+ g_error_free (error);
+ cups_get_jobs_data_free (data);
+ }
+ else
+ {
+ g_thread_unref (thread);
+ }
+}
+
+typedef struct
+{
+ GCancellable *cancellable;
+ JCPCallback callback;
+ gpointer user_data;
+} JCPData;
+
+static void
+job_cancel_purge_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVariant *output;
+ JCPData *data = (JCPData *) user_data;
+ GError *error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+ g_object_unref (source_object);
+
+ if (output)
+ {
+ g_variant_unref (output);
+ }
+ else
+ {
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ data->callback (data->user_data);
+
+ if (data->cancellable)
+ g_object_unref (data->cancellable);
+ g_free (data);
+}
+
+void
+job_cancel_purge_async (gint job_id,
+ gboolean job_purge,
+ GCancellable *cancellable,
+ JCPCallback callback,
+ gpointer user_data)
+{
+ GDBusConnection *bus;
+ JCPData *data;
+ GError *error = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get session bus: %s", error->message);
+ g_error_free (error);
+ callback (user_data);
+ return;
+ }
+
+ data = g_new0 (JCPData, 1);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "JobCancelPurge",
+ g_variant_new ("(ib)",
+ job_id,
+ job_purge),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ job_cancel_purge_async_dbus_cb,
+ data);
+}
+
+typedef struct
+{
+ GCancellable *cancellable;
+ JSHUCallback callback;
+ gpointer user_data;
+} JSHUData;
+
+static void
+job_set_hold_until_async_dbus_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GVariant *output;
+ JSHUData *data = (JSHUData *) user_data;
+ GError *error = NULL;
+
+ output = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res,
+ &error);
+ g_object_unref (source_object);
+
+ if (output)
+ {
+ g_variant_unref (output);
+ }
+ else
+ {
+ if (!g_cancellable_is_cancelled (data->cancellable))
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ data->callback (data->user_data);
+
+ if (data->cancellable)
+ g_object_unref (data->cancellable);
+ g_free (data);
+}
+
+void
+job_set_hold_until_async (gint job_id,
+ const gchar *job_hold_until,
+ GCancellable *cancellable,
+ JSHUCallback callback,
+ gpointer user_data)
+{
+ GDBusConnection *bus;
+ JSHUData *data;
+ GError *error = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (!bus)
+ {
+ g_warning ("Failed to get session bus: %s", error->message);
+ g_error_free (error);
+ callback (user_data);
+ return;
+ }
+
+ data = g_new0 (JSHUData, 1);
+ if (cancellable)
+ data->cancellable = g_object_ref (cancellable);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ g_dbus_connection_call (bus,
+ MECHANISM_BUS,
+ "/",
+ MECHANISM_BUS,
+ "JobSetHoldUntil",
+ g_variant_new ("(is)",
+ job_id,
+ job_hold_until),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ job_set_hold_until_async_dbus_cb,
+ data);
+}
diff --git a/panels/printers/pp-utils.h b/panels/printers/pp-utils.h
index 156b961..e2bc75dc 100644
--- a/panels/printers/pp-utils.h
+++ b/panels/printers/pp-utils.h
@@ -232,6 +232,32 @@ void printer_add_option_async (const gchar *printer_name,
PAOCallback callback,
gpointer user_data);
+typedef void (*CGJCallback) (cups_job_t *jobs,
+ gint num_of_jobs,
+ gpointer user_data);
+
+void cups_get_jobs_async (const gchar *printer_name,
+ gboolean my_jobs,
+ gint which_jobs,
+ CGJCallback callback,
+ gpointer user_data);
+
+typedef void (*JCPCallback) (gpointer user_data);
+
+void job_cancel_purge_async (gint job_id,
+ 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,
+ const gchar *job_hold_until,
+ GCancellable *cancellable,
+ JSHUCallback callback,
+ gpointer user_data);
+
G_END_DECLS
#endif /* __PP_UTILS_H */
diff --git a/panels/printers/printers.ui b/panels/printers/printers.ui
index 75b1483..ebedf01 100644
--- a/panels/printers/printers.ui
+++ b/panels/printers/printers.ui
@@ -237,7 +237,7 @@
</child>
<child>
<object class="GtkButton" id="printer-jobs-button">
- <property name="label" translatable="yes" comments="Tanslators: Switch to tab containing printer's jobs">_Show</property>
+ <property name="label" translatable="yes" comments="Tanslators: Opens a dialog containing printer's jobs">_Show</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -511,158 +511,6 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox2">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">10</property>
- <child>
- <object class="GtkTable" id="table3">
- <property name="visible">True</property>
- <property name="n_columns">3</property>
- <child>
- <object class="GtkButton" id="back-button-1">
- <property name="label" translatable="yes" comments="Translators: Switch back to printer's info tab">_Back</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">GTK_ALIGN_START</property>
- <property name="valign">GTK_ALIGN_CENTER</property>
- </object>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="label" translatable="yes" comments="Translators: This tab contains list of active print jobs of the selected printer">Active Print Jobs</property>
- <property name="halign">GTK_ALIGN_CENTER</property>
- <property name="valign">GTK_ALIGN_CENTER</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="back-spacer-label-1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox3">
- <property name="visible">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="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</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>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="queue-toolbar">
- <property name="visible">True</property>
- <property name="icon_size">1</property>
- <property name="icon_size_set">True</property>
- <style>
- <class name="inline-toolbar"/>
- </style>
- <child>
- <object class="GtkToolButton" id="job-release-button">
- <property name="visible">True</property>
- <property name="label">resume-toolbutton</property>
- <property name="use_underline">True</property>
- <property name="icon_name">media-playback-start-symbolic</property>
- <property name="label" translatable="yes">Resume Printing</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="label">pause-toolbutton</property>
- <property name="use_underline">True</property>
- <property name="icon_name">media-playback-pause-symbolic</property>
- <property name="label" translatable="yes">Pause Printing</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="label">stop-toolbutton</property>
- <property name="use_underline">True</property>
- <property name="icon_name">media-playback-stop-symbolic</property>
- <property name="label" translatable="yes">Cancel Print Job</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child type="tab">
- <object class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="label">Jobs</property>
- </object>
- <packing>
- <property name="position">1</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
<object class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="orientation">vertical</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]