From c6d8b9c8252cbf4e439cad0a225b841b2189fec0 Mon Sep 17 00:00:00 2001 From: Marek Kasik Date: Tue, 7 Aug 2012 14:09:33 +0200 Subject: [PATCH] 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(-) create mode 100644 panels/printers/jobs-dialog.ui create mode 100644 panels/printers/pp-jobs-dialog.c create mode 100644 panels/printers/pp-jobs-dialog.h diff --git a/panels/printers/Makefile.am b/panels/printers/Makefile.am index 249ce692b..0fb0c60c2 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 88cccff03..436e3ee56 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,318 +1256,48 @@ 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; + cc_editable_entry_set_text (CC_EDITABLE_ENTRY (widget), EMPTY_TEXT); - priv->current_job = id; - - 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, @@ -2783,21 +2462,6 @@ go_back_cb (GtkButton *button, gtk_notebook_set_current_page (GTK_NOTEBOOK (widget), NOTEBOOK_INFO_PAGE); } -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, @@ -2924,6 +2588,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) { @@ -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; @@ -2987,18 +2686,6 @@ cc_printers_panel_init (CcPrintersPanel *self) gtk_builder_get_object (priv->builder, "main-vbox"); /* 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); @@ -3027,17 +2714,13 @@ cc_printers_panel_init (CcPrintersPanel *self) gtk_builder_get_object (priv->builder, "print-test-page-button"); 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 000000000..d58be2c91 --- /dev/null +++ b/panels/printers/jobs-dialog.ui @@ -0,0 +1,183 @@ + + + + + 500 + 350 + False + 5 + + True + True + dialog + False + + + True + False + vertical + 2 + + + True + False + end + + + Close + False + True + True + True + False + + + False + True + 2 + + + + + False + True + end + 0 + + + + + True + False + + + True + False + vertical + 10 + + + True + False + 0 + Active Jobs + + + + + + False + False + 0 + + + + + True + False + vertical + + + True + True + in + + + True + True + + + + + + + + True + True + 0 + + + + + True + False + 1 + + + False + True + False + False + False + Resume Printing + True + media-playback-start-symbolic + + + False + True + + + + + False + True + False + False + False + Pause Printing + True + media-playback-pause-symbolic + + + False + True + + + + + False + True + False + False + False + Cancel Print Job + True + media-playback-stop-symbolic + + + False + True + + + + + False + True + 1 + + + + + True + True + 1 + + + + + + + True + True + 1 + + + + + + jobs-close-button + + + + diff --git a/panels/printers/pp-jobs-dialog.c b/panels/printers/pp-jobs-dialog.c new file mode 100644 index 000000000..eac73f668 --- /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 + */ + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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 000000000..72ae66b01 --- /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 + */ + +#ifndef __PP_JOBS_DIALOG_H__ +#define __PP_JOBS_DIALOG_H__ + +#include + +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 599bd1af6..b53c0bd28 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 156b9612a..e2bc75dc7 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 75b148399..ebedf01de 100644 --- a/panels/printers/printers.ui +++ b/panels/printers/printers.ui @@ -237,7 +237,7 @@ - _Show + _Show True True True @@ -510,158 +510,6 @@ False - - - True - vertical - 10 - - - True - 3 - - - _Back - True - True - True - True - GTK_ALIGN_START - GTK_ALIGN_CENTER - - - GTK_FILL - GTK_FILL - - - - - True - Active Print Jobs - GTK_ALIGN_CENTER - GTK_ALIGN_CENTER - - - - - - 1 - GTK_FILL - - - - - True - False - - - 2 - GTK_FILL - GTK_FILL - - - - - False - False - 0 - - - - - True - vertical - - - True - True - automatic - automatic - in - - - True - True - - - - - 0 - - - - - True - 1 - True - - - - True - resume-toolbutton - True - media-playback-start-symbolic - Resume Printing - - - False - True - - - - - True - pause-toolbutton - True - media-playback-pause-symbolic - Pause Printing - - - False - True - - - - - True - stop-toolbutton - True - media-playback-stop-symbolic - Cancel Print Job - - - False - True - - - - - False - 1 - - - - - 1 - - - - - 1 - - - - - True - Jobs - - - 1 - False - - True