diff --git a/configure.ac b/configure.ac index 9df2ca83d..b223fa289 100644 --- a/configure.ac +++ b/configure.ac @@ -106,6 +106,10 @@ PKG_CHECK_MODULES(PULSEAUDIO, libpulse-mainloop-glib >= $PA_REQUIRED_VERSION) AC_SUBST(PULSEAUDIO_CFLAGS) AC_SUBST(PULSEAUDIO_LIBS) +# check for cups +AC_CHECK_HEADERS(cups/cups.h cups/http.h cups/ipp.h) +CUPS_LIBS=-lcups +AC_SUBST(CUPS_LIBS) gtk_lib_dir=`$PKG_CONFIG --variable libdir gtk+-3.0` gtk_binary_version=`$PKG_CONFIG --variable gtk_binary_version gtk+-3.0` @@ -372,6 +376,8 @@ panels/info/Makefile panels/info/gnome-info-panel.desktop.in panels/power/Makefile panels/power/gnome-power-panel.desktop.in +panels/printers/Makefile +panels/printers/gnome-printers-panel.desktop.in panels/network/Makefile panels/network/gnome-network-panel.desktop.in panels/universal-access/Makefile diff --git a/panels/Makefile.am b/panels/Makefile.am index e43e42981..efd5cf605 100644 --- a/panels/Makefile.am +++ b/panels/Makefile.am @@ -5,6 +5,7 @@ SUBDIRS= \ display \ media \ mouse \ + printers \ region \ network \ info \ diff --git a/panels/printers/Makefile.am b/panels/printers/Makefile.am new file mode 100644 index 000000000..ff529ee47 --- /dev/null +++ b/panels/printers/Makefile.am @@ -0,0 +1,33 @@ +uidir = $(pkgdatadir)/ui/printers +dist_ui_DATA = \ + printers.ui + +INCLUDES = \ + $(PANEL_CFLAGS) \ + $(DBUS_CFLAGS) \ + $(GNOMECC_CAPPLETS_CFLAGS) \ + -DGNOMELOCALEDIR="\"$(datadir)/locale\"" \ + -DGNOMECC_DATA_DIR="\"$(pkgdatadir)\"" \ + -DDATADIR="\"$(uidir)\"" \ + $(NULL) + +ccpanelsdir = $(PANELS_DIR) +ccpanels_LTLIBRARIES = libprinters.la + +libprinters_la_SOURCES = \ + printers-module.c \ + cc-printers-panel.c \ + cc-printers-panel.h + +libprinters_la_LIBADD = $(PANEL_LIBS) $(CUPS_LIBS) $(DBUS_LIBS) +libprinters_la_LDFLAGS = $(PANEL_LDFLAGS) + +@INTLTOOL_DESKTOP_RULE@ + +desktopdir = $(datadir)/applications +desktop_in_files = gnome-printers-panel.desktop.in +desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) + +CLEANFILES = $(desktop_in_files) $(desktop_DATA) + +-include $(top_srcdir)/git.mk diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c new file mode 100644 index 000000000..18c238d7e --- /dev/null +++ b/panels/printers/cc-printers-panel.c @@ -0,0 +1,1021 @@ +/* + * Copyright (C) 2010 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "cc-printers-panel.h" + +#include +#include +#include + +#include + +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" + +struct _CcPrintersPanelPrivate +{ + GtkBuilder *builder; + + cups_dest_t *dests; + int num_dests; + int current_dest; + + cups_job_t *jobs; + int num_jobs; + int current_job; + + gchar **allowed_users; + int num_allowed_users; + int current_allowed_user; + + gpointer dummy; +}; + +static void actualize_jobs_list (CcPrintersPanel *self); +static void actualize_printers_list (CcPrintersPanel *self); +static void actualize_allowed_users_list (CcPrintersPanel *self); +static void printer_disable_cb (GtkToggleButton *togglebutton, gpointer user_data); + +static void +cc_printers_panel_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +cc_printers_panel_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +cc_printers_panel_dispose (GObject *object) +{ + G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object); +} + +static void +cc_printers_panel_finalize (GObject *object) +{ + G_OBJECT_CLASS (cc_printers_panel_parent_class)->finalize (object); +} + +static void +cc_printers_panel_class_init (CcPrintersPanelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (CcPrintersPanelPrivate)); + + object_class->get_property = cc_printers_panel_get_property; + object_class->set_property = cc_printers_panel_set_property; + object_class->dispose = cc_printers_panel_dispose; + object_class->finalize = cc_printers_panel_finalize; +} + +static void +cc_printers_panel_class_finalize (CcPrintersPanelClass *klass) +{ +} + +enum +{ + PRINTER_NAME_COLUMN, + PRINTER_ID_COLUMN, + PRINTER_N_COLUMNS +}; + +static void +printer_selection_changed_cb (GtkTreeSelection *selection, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + GtkTreeModel *model; + GtkTreeIter iter; + const gchar *none = "---"; + GtkWidget *widget; + gboolean paused = FALSE; + gchar *instance = NULL; + gchar *location = NULL; + gchar *device_uri = NULL; + int id, i; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + gtk_tree_model_get (model, &iter, + PRINTER_ID_COLUMN, &id, + -1); + else + id = -1; + + priv->current_dest = id; + + actualize_jobs_list (self); + actualize_allowed_users_list (self); + + if (priv->current_dest >= 0 && + priv->current_dest < priv->num_dests && + priv->dests != NULL) + { + if (priv->dests[id].instance) + instance = g_strdup_printf ("%s / %s", priv->dests[id].name, priv->dests[id].instance); + else + instance = g_strdup (priv->dests[id].name); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-name-label"); + gtk_label_set_text (GTK_LABEL (widget), instance); + g_free (instance); + + for (i = 0; i < priv->dests[id].num_options; i++) + { + if (g_strcmp0 (priv->dests[id].options[i].name, "printer-location") == 0) + location = g_strdup (priv->dests[id].options[i].value); + else if (g_strcmp0 (priv->dests[id].options[i].name, "device-uri") == 0) + device_uri = g_strdup (priv->dests[id].options[i].value); + else if (g_strcmp0 (priv->dests[id].options[i].name, "printer-state") == 0) + paused = (g_strcmp0 (priv->dests[id].options[i].value, "5") == 0); + } + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-location-label"); + + if (location) + { + gtk_label_set_text (GTK_LABEL (widget), location); + g_free (location); + } + else + gtk_label_set_text (GTK_LABEL (widget), none); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-URI-entry"); + if (device_uri) + { + gtk_entry_set_text (GTK_ENTRY (widget), device_uri); + g_free (device_uri); + } + else + gtk_entry_set_text (GTK_ENTRY (widget), none); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-disable-button"); + gtk_widget_set_sensitive (widget, TRUE); + g_signal_handlers_block_by_func(G_OBJECT (widget), printer_disable_cb, self); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), paused); + g_signal_handlers_unblock_by_func(G_OBJECT (widget), printer_disable_cb, self); + } + else + { + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-name-label"); + gtk_label_set_text (GTK_LABEL (widget), ""); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-location-label"); + gtk_label_set_text (GTK_LABEL (widget), ""); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-URI-entry"); + gtk_entry_set_text (GTK_ENTRY (widget), ""); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-disable-button"); + gtk_widget_set_sensitive (widget, FALSE); + } +} + +static void +actualize_printers_list (CcPrintersPanel *self) +{ + CcPrintersPanelPrivate *priv; + GtkListStore *store; + GtkTreeIter selected_iter; + GtkTreeView *treeview; + GtkTreeIter iter; + gchar *current_printer_instance = NULL; + gchar *current_printer_name = NULL; + int current_dest = -1; + int i; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (priv->current_dest >= 0 && + priv->current_dest < priv->num_dests && + priv->dests != NULL) + { + current_printer_name = g_strdup (priv->dests[priv->current_dest].name); + if (priv->dests[priv->current_dest].instance) + current_printer_instance = g_strdup (priv->dests[priv->current_dest].instance); + } + + priv->num_dests = cupsGetDests (&priv->dests); + priv->current_dest = -1; + + treeview = (GtkTreeView*) + gtk_builder_get_object (priv->builder, "printer-treeview"); + + store = gtk_list_store_new (PRINTER_N_COLUMNS, G_TYPE_STRING, G_TYPE_INT); + + for (i = 0; i < priv->num_dests; i++) + { + gchar *instance; + + gtk_list_store_append (store, &iter); + + if (priv->dests[i].instance) + { + instance = g_strdup_printf ("%s / %s", priv->dests[i].name, priv->dests[i].instance); + + if (current_printer_instance && + g_strcmp0 (current_printer_name, priv->dests[i].name) == 0 && + g_strcmp0 (current_printer_instance, priv->dests[i].instance) == 0) + { + current_dest = i; + selected_iter = iter; + } + } + else + { + instance = g_strdup (priv->dests[i].name); + + if (current_printer_instance == NULL && + g_strcmp0 (current_printer_name, priv->dests[i].name) == 0) + { + current_dest = i; + selected_iter = iter; + } + } + + + gtk_list_store_set (store, &iter, + PRINTER_NAME_COLUMN, instance, + PRINTER_ID_COLUMN, i, + -1); + g_free (instance); + } + + gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store)); + + if (current_dest >= 0) + { + priv->current_dest = current_dest; + gtk_tree_selection_select_iter ( + gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), + &selected_iter); + } +} + +static void +populate_printers_list (CcPrintersPanel *self) +{ + CcPrintersPanelPrivate *priv; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkWidget *treeview; + + priv = PRINTERS_PANEL_PRIVATE (self); + + treeview = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-treeview"); + + actualize_printers_list (self); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Printer", renderer, + "text", PRINTER_NAME_COLUMN, NULL); + + g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), + "changed", G_CALLBACK (printer_selection_changed_cb), self); + + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); +} + +enum +{ + JOB_ID_COLUMN, + JOB_TITLE_COLUMN, + JOB_STATE_COLUMN, + JOB_USER_COLUMN, + JOB_CREATION_TIME_COLUMN, + JOB_N_COLUMNS +}; + +static void +actualize_jobs_list (CcPrintersPanel *self) +{ + CcPrintersPanelPrivate *priv; + GtkListStore *store; + GtkTreeView *treeview; + GtkTreeIter iter; + int i; + + priv = PRINTERS_PANEL_PRIVATE (self); + + treeview = (GtkTreeView*) + gtk_builder_get_object (priv->builder, "job-treeview"); + + 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); + else + { + priv->num_jobs = -1; + priv->jobs = NULL; + } + + store = gtk_list_store_new (JOB_N_COLUMNS, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + for (i = 0; i < priv->num_jobs; i++) + { + struct tm *ts; + gchar *time_string; + gchar *state = NULL; + + ts = localtime(&(priv->jobs[i].creation_time)); + time_string = g_strdup_printf ("%02d:%02d:%02d", ts->tm_hour, ts->tm_min, ts->tm_sec); + + switch (priv->jobs[i].state) + { + case IPP_JOB_PENDING: + state = g_strdup (_("Pending")); + break; + case IPP_JOB_HELD: + state = g_strdup (_("Held")); + break; + case IPP_JOB_PROCESSING: + state = g_strdup (_("Processing")); + break; + case IPP_JOB_STOPPED: + state = g_strdup (_("Stopped")); + break; + case IPP_JOB_CANCELED: + state = g_strdup (_("Canceled")); + break; + case IPP_JOB_ABORTED: + state = g_strdup (_("Aborted")); + break; + case IPP_JOB_COMPLETED: + state = g_strdup (_("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_USER_COLUMN, priv->jobs[i].user, + JOB_CREATION_TIME_COLUMN, time_string, + -1); + + g_free (time_string); + g_free (state); + } + + gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store)); +} + +static void +job_selection_changed_cb (GtkTreeSelection *selection, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + GtkTreeModel *model; + GtkTreeIter iter; + int id; + + 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); + priv->current_job = id; +} + +static void +populate_jobs_list (CcPrintersPanel *self) +{ + + CcPrintersPanelPrivate *priv; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeView *treeview; + + priv = PRINTERS_PANEL_PRIVATE (self); + + actualize_jobs_list (self); + + treeview = (GtkTreeView*) + gtk_builder_get_object (priv->builder, "job-treeview"); + + renderer = gtk_cell_renderer_text_new (); + + column = gtk_tree_view_column_new_with_attributes (_("Job Title"), renderer, + "text", JOB_TITLE_COLUMN, NULL); + gtk_tree_view_append_column (treeview, column); + + column = gtk_tree_view_column_new_with_attributes (_("Job State"), renderer, + "text", JOB_STATE_COLUMN, NULL); + gtk_tree_view_append_column (treeview, column); + + column = gtk_tree_view_column_new_with_attributes (_("User"), renderer, + "text", JOB_USER_COLUMN, NULL); + gtk_tree_view_append_column (treeview, column); + + column = gtk_tree_view_column_new_with_attributes (_("Time"), renderer, + "text", JOB_CREATION_TIME_COLUMN, NULL); + gtk_tree_view_append_column (treeview, column); + + g_signal_connect (gtk_tree_view_get_selection (treeview), + "changed", G_CALLBACK (job_selection_changed_cb), self); +} + +enum +{ + ALLOWED_USERS_ID_COLUMN, + ALLOWED_USERS_NAME_COLUMN, + ALLOWED_USERS_N_COLUMNS +}; + +static int +ccGetAllowedUsers (gchar ***allowed_users, char *printer_name) +{ + const char * const attrs[1] = { "requesting-user-name-allowed" }; + http_t *http; + ipp_t *request = NULL; + gchar **users = NULL; + ipp_t *response; + char uri[HTTP_MAX_URI + 1]; + int num_allowed_users = 0; + + http = httpConnectEncrypt (cupsServer (), + ippPort (), + cupsEncryption ()); + + if (http || !allowed_users) + { + request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES); + + g_snprintf (uri, sizeof (uri), "ipp://localhost/printers/%s", printer_name); + ippAddString (request, + IPP_TAG_OPERATION, + IPP_TAG_URI, + "printer-uri", + NULL, + uri); + ippAddStrings (request, + IPP_TAG_OPERATION, + IPP_TAG_KEYWORD, + "requested-attributes", + 1, + NULL, + attrs); + + response = cupsDoRequest (http, request, "/"); + if (response) + { + ipp_attribute_t *attr = NULL; + ipp_attribute_t *allowed = NULL; + + for (attr = response->attrs; attr != NULL; attr = attr->next) + { + if (attr->group_tag == IPP_TAG_PRINTER && + attr->value_tag == IPP_TAG_NAME && + !g_strcmp0(attr->name, "requesting-user-name-allowed")) + allowed = attr; + } + + if (allowed && allowed->num_values > 0) + { + int i; + + num_allowed_users = allowed->num_values; + users = g_new (gchar*, num_allowed_users); + + for (i = 0; i < num_allowed_users; i ++) + users[i] = g_strdup (allowed->values[i].string.text); + } + } + } + + *allowed_users = users; + return num_allowed_users; +} + +static void +actualize_allowed_users_list (CcPrintersPanel *self) +{ + CcPrintersPanelPrivate *priv; + GtkListStore *store; + GtkTreeView *treeview; + GtkTreeIter iter; + int i; + + priv = PRINTERS_PANEL_PRIVATE (self); + + treeview = (GtkTreeView*) + gtk_builder_get_object (priv->builder, "allowed-users-treeview"); + + if (priv->allowed_users) + { + for (i = 0; i < priv->num_allowed_users; i++) + g_free (priv->allowed_users[i]); + g_free (priv->allowed_users); + priv->allowed_users = NULL; + priv->num_allowed_users = 0; + } + + priv->current_allowed_user = -1; + + if (priv->current_dest >= 0 && + priv->current_dest < priv->num_dests && + priv->dests != NULL) + priv->num_allowed_users = ccGetAllowedUsers (&priv->allowed_users, priv->dests[priv->current_dest].name); + + store = gtk_list_store_new (ALLOWED_USERS_N_COLUMNS, G_TYPE_INT, G_TYPE_STRING); + + for (i = 0; i < priv->num_allowed_users; i++) + { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + ALLOWED_USERS_ID_COLUMN, i, + ALLOWED_USERS_NAME_COLUMN, priv->allowed_users[i], + -1); + } + + gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store)); +} + +static void +allowed_users_selection_changed_cb (GtkTreeSelection *selection, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + GtkTreeModel *model; + GtkTreeIter iter; + int id; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + gtk_tree_model_get (model, &iter, + ALLOWED_USERS_ID_COLUMN, &id, + -1); + priv->current_allowed_user = id; +} + +static void +populate_allowed_users_list (CcPrintersPanel *self) +{ + + CcPrintersPanelPrivate *priv; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeView *treeview; + + priv = PRINTERS_PANEL_PRIVATE (self); + + actualize_allowed_users_list (self); + + treeview = (GtkTreeView*) + gtk_builder_get_object (priv->builder, "allowed-users-treeview"); + + gtk_tree_view_set_headers_visible (treeview, FALSE); + + renderer = gtk_cell_renderer_text_new (); + + column = gtk_tree_view_column_new_with_attributes (NULL, renderer, + "text", ALLOWED_USERS_NAME_COLUMN, NULL); + gtk_tree_view_append_column (treeview, column); + + g_signal_connect (gtk_tree_view_get_selection (treeview), + "changed", G_CALLBACK (allowed_users_selection_changed_cb), self); +} + +static DBusGProxy * +get_dbus_proxy () +{ + DBusGConnection *system_bus; + DBusGProxy *proxy; + GError *error; + + error = NULL; + system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (system_bus == NULL) + { + g_warning (_("Could not connect to system bus: %s"), + error->message); + g_error_free (error); + return NULL; + } + + error = NULL; + + proxy = dbus_g_proxy_new_for_name (system_bus, + MECHANISM_BUS, + "/", + MECHANISM_BUS); + return proxy; +} + +static void +job_process_cb (GtkToolButton *toolbutton, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + DBusGProxy *proxy; + gboolean ret = FALSE; + GError *error = NULL; + char *ret_error = 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) + { + proxy = get_dbus_proxy (); + + if (!proxy) + return; + + if ((GtkToolButton*) gtk_builder_get_object (priv->builder, + "job-cancel-button") == + toolbutton) + ret = dbus_g_proxy_call (proxy, "JobCancelPurge", &error, + G_TYPE_INT, id, + G_TYPE_BOOLEAN, FALSE, + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + else if ((GtkToolButton*) gtk_builder_get_object (priv->builder, + "job-delete-button") == + toolbutton) + ret = dbus_g_proxy_call (proxy, "JobCancelPurge", &error, + G_TYPE_INT, id, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + else if ((GtkToolButton*) gtk_builder_get_object (priv->builder, + "job-pause-button") == + toolbutton) + ret = dbus_g_proxy_call (proxy, "JobSetHoldUntil", &error, + G_TYPE_INT, id, + G_TYPE_STRING, "indefinite", + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + else if ((GtkToolButton*) gtk_builder_get_object (priv->builder, + "job-release-button") == + toolbutton) + ret = dbus_g_proxy_call (proxy, "JobSetHoldUntil", &error, + G_TYPE_INT, id, + G_TYPE_STRING, "no-hold", + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + + if (error || (ret_error && ret_error[0] != '\0')) + { + if (error) + g_warning ("%s", error->message); + + if (ret_error && ret_error[0] != '\0') + g_warning ("%s", ret_error); + } + else + actualize_jobs_list (self); + } + + return; +} + +static void +printer_disable_cb (GtkToggleButton *togglebutton, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + DBusGProxy *proxy; + gboolean ret = FALSE; + gboolean paused = FALSE; + GError *error = NULL; + char *ret_error = NULL; + char *name = NULL; + int i; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (priv->current_dest >= 0 && + priv->current_dest < priv->num_dests && + priv->dests != NULL) + { + name = priv->dests[priv->current_dest].name; + + for (i = 0; i < priv->dests[priv->current_dest].num_options; i++) + { + if (g_strcmp0 (priv->dests[priv->current_dest].options[i].name, "printer-state") == 0) + paused = (g_strcmp0 (priv->dests[priv->current_dest].options[i].value, "5") == 0); + } + } + + if (name) + { + proxy = get_dbus_proxy (); + + if (!proxy) + return; + + ret = dbus_g_proxy_call (proxy, "PrinterSetEnabled", &error, + G_TYPE_STRING, name, + G_TYPE_BOOLEAN, paused, + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + + if (error || (ret_error && ret_error[0] != '\0')) + { + if (error) + g_warning ("%s", error->message); + + if (ret_error && ret_error[0] != '\0') + g_warning ("%s", ret_error); + } + else + { + gtk_toggle_button_set_active (togglebutton, paused); + actualize_printers_list (self); + } + } + + return; +} + +static void +printer_delete_cb (GtkToolButton *toolbutton, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + DBusGProxy *proxy; + gboolean ret = FALSE; + GError *error = NULL; + char *ret_error = NULL; + char *name = NULL; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (priv->current_dest >= 0 && + priv->current_dest < priv->num_dests && + priv->dests != NULL) + name = priv->dests[priv->current_dest].name; + + if (name) + { + proxy = get_dbus_proxy (); + + if (!proxy) + return; + + ret = dbus_g_proxy_call (proxy, "PrinterDelete", &error, + G_TYPE_STRING, name, + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + + if (error || (ret_error && ret_error[0] != '\0')) + { + if (error) + g_warning ("%s", error->message); + + if (ret_error && ret_error[0] != '\0') + g_warning ("%s", ret_error); + } + else + actualize_printers_list (self); + } + + return; +} + +static void +allowed_user_remove_cb (GtkToolButton *toolbutton, + gpointer user_data) +{ + CcPrintersPanelPrivate *priv; + CcPrintersPanel *self = (CcPrintersPanel*) user_data; + DBusGProxy *proxy; + gboolean ret = FALSE; + GError *error = NULL; + char *ret_error = NULL; + char *printer_name = NULL; + char **names = NULL; + char *name = NULL; + int i, j; + + priv = PRINTERS_PANEL_PRIVATE (self); + + if (priv->current_allowed_user >= 0 && + priv->current_allowed_user < priv->num_allowed_users && + priv->allowed_users != NULL) + name = priv->allowed_users[priv->current_allowed_user]; + + if (priv->current_dest >= 0 && + priv->current_dest < priv->num_dests && + priv->dests != NULL) + printer_name = priv->dests[priv->current_dest].name; + + if (name && printer_name) + { + proxy = get_dbus_proxy (); + + if (!proxy) + return; + + names = g_new0 (gchar*, priv->num_allowed_users); + j = 0; + for (i = 0; i < (priv->num_allowed_users); i++) + { + if (i != priv->current_allowed_user) + { + names[j] = priv->allowed_users[i]; + j++; + } + } + + ret = dbus_g_proxy_call (proxy, "PrinterSetUsersAllowed", &error, + G_TYPE_STRING, printer_name, + G_TYPE_STRV, names, + G_TYPE_INVALID, + G_TYPE_STRING, &ret_error, + G_TYPE_INVALID); + + if (error || (ret_error && ret_error[0] != '\0')) + { + if (error) + g_warning ("%s", error->message); + + if (ret_error && ret_error[0] != '\0') + g_warning ("%s", ret_error); + } + else + actualize_allowed_users_list (self); + } + + return; +} + +static void +cc_printers_panel_init (CcPrintersPanel *self) +{ + CcPrintersPanelPrivate *priv; + GtkWidget *top_widget; + GtkWidget *widget; + GError *error = NULL; + gchar *objects[] = { "main-vbox", NULL }; + + priv = self->priv = PRINTERS_PANEL_PRIVATE (self); + + /* initialize main data structure */ + priv->builder = gtk_builder_new (); + priv->dests = NULL; + priv->num_dests = 0; + priv->current_dest = -1; + + priv->jobs = NULL; + priv->num_jobs = 0; + priv->current_job = -1; + + priv->allowed_users = NULL; + priv->num_allowed_users = 0; + priv->current_allowed_user = -1; + + gtk_builder_add_objects_from_file (priv->builder, + DATADIR"/printers.ui", + objects, &error); + + if (error) + { + g_warning (_("Could not load ui: %s"), error->message); + g_error_free (error); + return; + } + + /* add the top level widget */ + top_widget = (GtkWidget*) + 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-delete-button"); + g_signal_connect (widget, "clicked", G_CALLBACK (job_process_cb), self); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "job-pause-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-disable-button"); + g_signal_connect (widget, "toggled", G_CALLBACK (printer_disable_cb), self); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-delete-button"); + g_signal_connect (widget, "clicked", G_CALLBACK (printer_delete_cb), self); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "allowed-user-remove-button"); + g_signal_connect (widget, "clicked", G_CALLBACK (allowed_user_remove_cb), self); + + + /* make unused widgets insensitive for now */ + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "allowed-user-add-button"); + gtk_widget_set_sensitive (widget, FALSE); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "printer-add-button"); + gtk_widget_set_sensitive (widget, FALSE); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "print-test-page-button"); + gtk_widget_set_sensitive (widget, FALSE); + + widget = (GtkWidget*) + gtk_builder_get_object (priv->builder, "clean-print-heads-button"); + gtk_widget_set_sensitive (widget, FALSE); + + populate_printers_list (self); + populate_jobs_list (self); + populate_allowed_users_list (self); + + gtk_container_add (GTK_CONTAINER (self), top_widget); + gtk_widget_show_all (GTK_WIDGET (self)); +} + +void +cc_printers_panel_register (GIOModule *module) +{ + cc_printers_panel_register_type (G_TYPE_MODULE (module)); + g_io_extension_point_implement (CC_SHELL_PANEL_EXTENSION_POINT, + CC_TYPE_PRINTERS_PANEL, + "printers", 0); +} + diff --git a/panels/printers/cc-printers-panel.h b/panels/printers/cc-printers-panel.h new file mode 100644 index 000000000..506e8ca84 --- /dev/null +++ b/panels/printers/cc-printers-panel.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _CC_PRINTERS_PANEL_H +#define _CC_PRINTERS_PANEL_H + +#include + +G_BEGIN_DECLS + +#define CC_TYPE_PRINTERS_PANEL cc_printers_panel_get_type() + +#define CC_PRINTERS_PANEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CC_TYPE_PRINTERS_PANEL, CcPrintersPanel)) + +#define CC_PRINTERS_PANEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CC_TYPE_PRINTERS_PANEL, CcPrintersPanelClass)) + +#define CC_IS_PRINTERS_PANEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CC_TYPE_PRINTERS_PANEL)) + +#define CC_IS_PRINTERS_PANEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CC_TYPE_PRINTERS_PANEL)) + +#define CC_PRINTERS_PANEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CC_TYPE_PRINTERS_PANEL, CcPrintersPanelClass)) + +typedef struct _CcPrintersPanel CcPrintersPanel; +typedef struct _CcPrintersPanelClass CcPrintersPanelClass; +typedef struct _CcPrintersPanelPrivate CcPrintersPanelPrivate; + +struct _CcPrintersPanel +{ + CcPanel parent; + + CcPrintersPanelPrivate *priv; +}; + +struct _CcPrintersPanelClass +{ + CcPanelClass parent_class; +}; + +GType cc_printers_panel_get_type (void) G_GNUC_CONST; + +void cc_printers_panel_register (GIOModule *module); + +G_END_DECLS + +#endif /* _CC_PRINTERS_PANEL_H */ diff --git a/panels/printers/gnome-printers-panel.desktop.in.in b/panels/printers/gnome-printers-panel.desktop.in.in new file mode 100644 index 000000000..d1e139a79 --- /dev/null +++ b/panels/printers/gnome-printers-panel.desktop.in.in @@ -0,0 +1,14 @@ +[Desktop Entry] +_Name=Printers +_Comment=Change printer settings +Exec=gnome-control-center printers +Icon=printer +Terminal=false +Type=Application +StartupNotify=true +# The X-GNOME-Settings-Panel is necessary to show in the main shell UI +Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel; +OnlyShowIn=GNOME; +X-GNOME-Settings-Panel=printers +# Translators: those are keywords for the printing control-center panel +_X-GNOME-Keywords=Foo;Bar;Baz; diff --git a/panels/printers/printers-module.c b/panels/printers/printers-module.c new file mode 100644 index 000000000..fcde59492 --- /dev/null +++ b/panels/printers/printers-module.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include "cc-printers-panel.h" + +#include + +void +g_io_module_load (GIOModule *module) +{ + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + + /* register the panel */ + cc_printers_panel_register (module); +} + +void +g_io_module_unload (GIOModule *module) +{ +} diff --git a/panels/printers/printers.ui b/panels/printers/printers.ui new file mode 100644 index 000000000..ed9187179 --- /dev/null +++ b/panels/printers/printers.ui @@ -0,0 +1,420 @@ + + + + + + 10 + vertical + 10 + + + 675 + 337 + True + 10 + + + 180 + True + vertical + + + True + True + False + + + 0 + + + + + True + icons + + + True + Add new printer + AddPrinter + True + gtk-add + + + False + True + + + + + True + Remove selected printer + RemovePrinter + True + gtk-remove + + + False + True + + + + + False + 1 + + + + + False + 0 + + + + + True + vertical + + + True + 5 + 2 + 10 + 10 + + + True + vertical + + + 60 + True + True + + + False + False + 0 + + + + + True + + + True + toolbutton7 + True + gtk-add + + + False + True + + + + + True + toolbutton8 + True + gtk-remove + + + False + True + + + + + False + 1 + + + + + 1 + 2 + 4 + 5 + + + + + True + 1 + 0 + Share with these users: + + + 4 + 5 + GTK_FILL + GTK_FILL + + + + + True + 1 + Printer URI: + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + 1 + Ink: + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + 1 + Location: + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + 1 + Printer: + + + GTK_FILL + GTK_FILL + + + + + True + True + + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + 0 + --- + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + 0 + --- + + + 1 + 2 + GTK_FILL + + + + + 0 + + + + + True + True + edge + + + Print Test Page + True + True + True + + + False + False + 0 + + + + + Clean Print Heads + True + True + True + + + False + False + 1 + + + + + Disable Printer + True + True + True + 0.43999999761581421 + + + False + False + 2 + + + + + False + False + end + 1 + + + + + 1 + + + + + 0 + + + + + True + True + + + True + vertical + + + True + + + True + Cancel selected job + toolbutton3 + True + gtk-cancel + + + False + True + + + + + True + Delete selected job + toolbutton4 + True + gtk-delete + + + False + True + + + + + True + Pause selected job + toolbutton5 + True + gtk-media-pause + + + False + True + + + + + True + Release selected job + toolbutton6 + True + gtk-media-play + + + False + True + + + + + False + 0 + + + + + 100 + True + True + + + 1 + + + + + + + True + Show / hide printer's jobs + Printer Queue + + + + + False + end + 1 + + + +