diff --git a/panels/printers/Makefile.am b/panels/printers/Makefile.am index 229149c54..575cda38c 100644 --- a/panels/printers/Makefile.am +++ b/panels/printers/Makefile.am @@ -45,6 +45,8 @@ libprinters_la_SOURCES = \ pp-job.h \ pp-jobs-dialog.c \ pp-jobs-dialog.h \ + pp-details-dialog.c \ + pp-details-dialog.h \ pp-samba.c \ pp-samba.h \ pp-print-device.c \ diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c index c41182f8c..9a17682cf 100644 --- a/panels/printers/cc-printers-panel.c +++ b/panels/printers/cc-printers-panel.c @@ -525,7 +525,7 @@ enum static void on_printer_changed (PpPrinterEntry *printer_entry, - gpointer user_data) + gpointer user_data) { actualize_printers_list (user_data); } diff --git a/panels/printers/details-dialog.ui b/panels/printers/details-dialog.ui new file mode 100644 index 000000000..c90a2368f --- /dev/null +++ b/panels/printers/details-dialog.ui @@ -0,0 +1,200 @@ + + + + + + + + horizontal + + + + + + + diff --git a/panels/printers/pp-details-dialog.c b/panels/printers/pp-details-dialog.c new file mode 100644 index 000000000..e530713d0 --- /dev/null +++ b/panels/printers/pp-details-dialog.c @@ -0,0 +1,447 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright 2016 Red Hat, Inc, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Author: Felipe Borges + */ + +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "cc-editable-entry.h" +#include "pp-details-dialog.h" +#include "pp-ppd-selection-dialog.h" +#include "pp-utils.h" + +struct _PpDetailsDialog { + GtkDialog parent; + + GtkEntry *printer_name_entry; + GtkEntry *printer_location_entry; + GtkLabel *printer_address_label; + GtkLabel *printer_model_label; + GtkStack *printer_model_stack; + GtkWidget *search_for_drivers_button; + + gchar *printer_name; + gchar *printer_location; + gchar *ppd_file_name; + PPDList *all_ppds_list; + GCancellable *get_all_ppds_cancellable; + GCancellable *get_ppd_names_cancellable; + + /* Dialogs */ + PpPPDSelectionDialog *pp_ppd_selection_dialog; +}; + +struct _PpDetailsDialogClass +{ + GtkDialogClass parent_class; +}; + +G_DEFINE_TYPE (PpDetailsDialog, pp_details_dialog, GTK_TYPE_DIALOG); + +static gboolean +printer_name_edit_cb (GtkWidget *entry, + GdkEventFocus *event, + PpDetailsDialog *self) +{ + const gchar *new_name; + + new_name = gtk_entry_get_text (GTK_ENTRY (self->printer_name_entry)); + if (g_strcmp0 (self->printer_name, new_name) != 0) + { + printer_rename (self->printer_name, new_name); + + self->printer_name = g_strdup (new_name); + } + + return FALSE; +} + +static void +printer_name_changed (GtkEditable *editable, + gpointer user_data) +{ + PpDetailsDialog *self = (PpDetailsDialog *) user_data; + GtkWidget *widget; + const gchar *name; + gchar *title; + + name = gtk_entry_get_text (GTK_ENTRY (self->printer_name_entry)); + + /* Translators: This is the title of the dialog. %s is the printer name. */ + title = g_strdup_printf (_("%s Details"), name); + + widget = gtk_dialog_get_header_bar (GTK_DIALOG (self)); + gtk_header_bar_set_title (GTK_HEADER_BAR (widget), title); + + g_free (title); +} + +static gboolean +printer_location_edit_cb (GtkWidget *entry, + GdkEventFocus *event, + PpDetailsDialog *self) +{ + const gchar *location; + + location = gtk_entry_get_text (GTK_ENTRY (self->printer_location_entry)); + if (g_strcmp0 (self->printer_location, location) != 0) + { + printer_set_location (self->printer_name, location); + + self->printer_location = g_strdup (location); + } + + return FALSE; +} + +static void +ppd_names_free (gpointer user_data) +{ + PPDName **names = (PPDName **) user_data; + gint i; + + if (names) + { + for (i = 0; names[i]; i++) + { + g_free (names[i]->ppd_name); + g_free (names[i]->ppd_display_name); + g_free (names[i]); + } + + g_free (names); + } +} + +static void set_ppd_cb (gchar *printer_name, gboolean success, gpointer user_data); + +static void +get_ppd_names_cb (PPDName **names, + const gchar *printer_name, + gboolean cancelled, + gpointer user_data) +{ + PpDetailsDialog *self = (PpDetailsDialog*) user_data; + + if (!cancelled) + { + if (names != NULL) + { + gtk_label_set_text (self->printer_model_label, names[0]->ppd_display_name); + printer_set_ppd_async (printer_name, + names[0]->ppd_name, + self->get_ppd_names_cancellable, + set_ppd_cb, + self); + ppd_names_free (names); + } + else + { + gtk_label_set_text (self->printer_model_label, _("No suitable driver found")); + } + + gtk_stack_set_visible_child_name (self->printer_model_stack, "printer_model_label"); + } +} + +static void +search_for_drivers (GtkButton *button, + PpDetailsDialog *self) +{ + gtk_stack_set_visible_child_name (self->printer_model_stack, "loading"); + gtk_widget_set_sensitive (self->search_for_drivers_button, FALSE); + + self->get_ppd_names_cancellable = g_cancellable_new (); + get_ppd_names_async (self->printer_name, + 1, + self->get_ppd_names_cancellable, + get_ppd_names_cb, + self); +} + +static void +set_ppd_cb (gchar *printer_name, + gboolean success, + gpointer user_data) +{ + PpDetailsDialog *self = (PpDetailsDialog*) user_data; + + gtk_label_set_text (GTK_LABEL (self->printer_model_label), self->ppd_file_name); +} + +static void +ppd_selection_dialog_response_cb (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + PpDetailsDialog *self = (PpDetailsDialog*) user_data; + + if (response_id == GTK_RESPONSE_OK) + { + gchar *ppd_name; + + ppd_name = pp_ppd_selection_dialog_get_ppd_name (self->pp_ppd_selection_dialog); + + if (self->printer_name && ppd_name) + { + GCancellable *cancellable; + + cancellable = g_cancellable_new (); + + printer_set_ppd_async (self->printer_name, + ppd_name, + cancellable, + set_ppd_cb, + self); + + g_clear_pointer (&self->ppd_file_name, g_free); + self->ppd_file_name = g_strdup (ppd_name); + } + + g_free (ppd_name); + } + + pp_ppd_selection_dialog_free (self->pp_ppd_selection_dialog); + self->pp_ppd_selection_dialog = NULL; +} + +static void +get_all_ppds_async_cb (PPDList *ppds, + gpointer user_data) +{ + PpDetailsDialog *self = user_data; + + self->all_ppds_list = ppds; + + if (self->pp_ppd_selection_dialog) + pp_ppd_selection_dialog_set_ppd_list (self->pp_ppd_selection_dialog, + self->all_ppds_list); + + g_object_unref (self->get_all_ppds_cancellable); + self->get_all_ppds_cancellable = NULL; +} + +static void +select_ppd_in_dialog (GtkButton *button, + PpDetailsDialog *self) +{ + gchar *device_id = NULL; + gchar *manufacturer = NULL; + + g_clear_pointer (&self->ppd_file_name, g_free); + self->ppd_file_name = g_strdup (cupsGetPPD (self->printer_name)); + + if (!self->pp_ppd_selection_dialog) + { + device_id = + get_ppd_attribute (self->ppd_file_name, + "1284DeviceID"); + + if (device_id) + { + manufacturer = get_tag_value (device_id, "mfg"); + if (!manufacturer) + manufacturer = get_tag_value (device_id, "manufacturer"); + } + + if (manufacturer == NULL) + { + manufacturer = + get_ppd_attribute (self->ppd_file_name, + "Manufacturer"); + } + + if (manufacturer == NULL) + { + manufacturer = g_strdup ("Raw"); + } + + if (self->all_ppds_list == NULL) + { + self->get_all_ppds_cancellable = g_cancellable_new (); + get_all_ppds_async (self->get_all_ppds_cancellable, get_all_ppds_async_cb, self); + } + + self->pp_ppd_selection_dialog = pp_ppd_selection_dialog_new ( + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))), + self->all_ppds_list, + manufacturer, + ppd_selection_dialog_response_cb, + self); + + g_free (manufacturer); + g_free (device_id); + } +} + +static void +select_ppd_manually (GtkButton *button, + PpDetailsDialog *self) +{ + GtkFileFilter *filter; + GtkWidget *dialog; + + dialog = gtk_file_chooser_dialog_new (_("Select PPD File"), + GTK_WINDOW (self), + GTK_FILE_CHOOSER_ACTION_OPEN, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Open"), GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, + _("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)")); + gtk_file_filter_add_pattern (filter, "*.ppd"); + gtk_file_filter_add_pattern (filter, "*.PPD"); + gtk_file_filter_add_pattern (filter, "*.ppd.gz"); + gtk_file_filter_add_pattern (filter, "*.PPD.gz"); + gtk_file_filter_add_pattern (filter, "*.PPD.GZ"); + + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) + { + gchar *ppd_filename; + + ppd_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + if (self->printer_name && ppd_filename) + { + printer_set_ppd_file_async (self->printer_name, + ppd_filename, + NULL, + set_ppd_cb, + self); + } + + g_free (ppd_filename); + } + + gtk_widget_destroy (dialog); +} + +static void +pp_details_dialog_init (PpDetailsDialog *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} + +static void +pp_details_dialog_class_init (PpDetailsDialogClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/details-dialog.ui"); + + gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_name_entry); + gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_location_entry); + gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_address_label); + gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_model_label); + gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_model_stack); + gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, search_for_drivers_button); + + gtk_widget_class_bind_template_callback (widget_class, printer_name_edit_cb); + gtk_widget_class_bind_template_callback (widget_class, printer_name_changed); + gtk_widget_class_bind_template_callback (widget_class, printer_location_edit_cb); + gtk_widget_class_bind_template_callback (widget_class, search_for_drivers); + gtk_widget_class_bind_template_callback (widget_class, select_ppd_in_dialog); + gtk_widget_class_bind_template_callback (widget_class, select_ppd_manually); +} + +PpDetailsDialog * +pp_details_dialog_new (GtkWindow *parent, + gchar *printer_name, + gchar *printer_location, + gchar *printer_address, + gchar *printer_make_and_model, + gboolean sensitive) +{ + PpDetailsDialog *self; + gchar *title; + gchar *printer_url; + + self = g_object_new (PP_DETAILS_DIALOG_TYPE, + "transient-for", parent, + "use-header-bar", TRUE, + NULL); + + self->printer_name = g_strdup (printer_name); + self->printer_location = g_strdup (printer_location); + self->ppd_file_name = NULL; + + /* Translators: This is the title of the dialog. %s is the printer name. */ + title = g_strdup_printf (_("%s Details"), printer_name); + gtk_window_set_title (GTK_WINDOW (self), title); + + printer_url = g_strdup_printf ("%s", printer_address, ippPort (), printer_address); + gtk_label_set_markup (GTK_LABEL (self->printer_address_label), printer_url); + g_free (printer_url); + + gtk_entry_set_text (GTK_ENTRY (self->printer_name_entry), printer_name); + gtk_entry_set_text (GTK_ENTRY (self->printer_location_entry), printer_location); + gtk_label_set_text (GTK_LABEL (self->printer_model_label), printer_make_and_model); + + gtk_widget_set_sensitive (gtk_dialog_get_content_area (GTK_DIALOG (self)), sensitive); + + return self; +} + +void +pp_details_dialog_free (PpDetailsDialog *self) +{ + if (self != NULL) + { + g_clear_pointer (&self->printer_name, g_free); + g_clear_pointer (&self->printer_location, g_free); + g_clear_pointer (&self->ppd_file_name, g_free); + + if (self->all_ppds_list != NULL) + { + ppd_list_free (self->all_ppds_list); + self->all_ppds_list = NULL; + } + + if (self->get_all_ppds_cancellable != NULL) + { + g_cancellable_cancel (self->get_all_ppds_cancellable); + g_clear_object (&self->get_all_ppds_cancellable); + } + + if (self->get_ppd_names_cancellable != NULL) + { + g_cancellable_cancel (self->get_ppd_names_cancellable); + g_object_unref (self->get_ppd_names_cancellable); + self->get_ppd_names_cancellable = NULL; + } + + gtk_widget_destroy (GTK_WIDGET (self)); + } +} diff --git a/panels/printers/pp-details-dialog.h b/panels/printers/pp-details-dialog.h new file mode 100644 index 000000000..266ce5afe --- /dev/null +++ b/panels/printers/pp-details-dialog.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright 2016 Red Hat, Inc, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Author: Felipe Borges + */ + +#ifndef __PP_DETAILS_DIALOG_H__ +#define __PP_DETAILS_DIALOG_H__ + +#include +#include "pp-utils.h" + +G_BEGIN_DECLS + +#define PP_DETAILS_DIALOG_TYPE (pp_details_dialog_get_type ()) +#define PP_DETAILS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PP_DETAILS_DIALOG_TYPE, PpDetailsDialog)) + +typedef struct _PpDetailsDialog PpDetailsDialog; +typedef struct _PpDetailsDialogClass PpDetailsDialogClass; + +GType pp_details_dialog_get_type (void); + +PpDetailsDialog *pp_details_dialog_new (GtkWindow *parent, + gchar *printer_name, + gchar *printer_location, + gchar *printer_address, + gchar *printer_make_and_model, + gboolean sensitive); +void pp_details_dialog_free (PpDetailsDialog *dialog); + +G_END_DECLS + +#endif diff --git a/panels/printers/pp-printer-entry.c b/panels/printers/pp-printer-entry.c index 94d2acc34..7b76d72e0 100644 --- a/panels/printers/pp-printer-entry.c +++ b/panels/printers/pp-printer-entry.c @@ -24,6 +24,7 @@ #include #include +#include "pp-details-dialog.h" #include "pp-options-dialog.h" #include "pp-jobs-dialog.h" #include "pp-utils.h" @@ -61,6 +62,7 @@ struct _PpPrinterEntry GtkLabel *error_status; /* Dialogs */ + PpDetailsDialog *pp_details_dialog; PpOptionsDialog *pp_options_dialog; PpJobsDialog *pp_jobs_dialog; }; @@ -282,6 +284,35 @@ supply_levels_draw_cb (GtkWidget *widget, return TRUE; } +static void +details_dialog_cb (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + PpPrinterEntry *self = PP_PRINTER_ENTRY (user_data); + + pp_details_dialog_free (self->pp_details_dialog); + self->pp_details_dialog = NULL; + + g_signal_emit_by_name (self, "printer-changed"); +} + +static void +on_show_printer_details_dialog (GtkButton *button, + PpPrinterEntry *self) +{ + self->pp_details_dialog = pp_details_dialog_new ( + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))), + self->printer_name, + self->printer_location, + self->printer_hostname, + self->printer_make_and_model, + self->is_authorized); + + g_signal_connect (self->pp_details_dialog, "response", G_CALLBACK (details_dialog_cb), self); + gtk_widget_show_all (GTK_WIDGET (self->pp_details_dialog)); +} + static void printer_options_dialog_cb (GtkDialog *dialog, gint response_id, @@ -685,6 +716,7 @@ pp_printer_entry_class_init (PpPrinterEntryClass *klass) gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, error_status); gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_error); + gtk_widget_class_bind_template_callback (widget_class, on_show_printer_details_dialog); gtk_widget_class_bind_template_callback (widget_class, on_show_printer_options_dialog); gtk_widget_class_bind_template_callback (widget_class, set_as_default_printer); gtk_widget_class_bind_template_callback (widget_class, remove_printer); diff --git a/panels/printers/printer-entry.ui b/panels/printers/printer-entry.ui index 1716de146..31cbc82aa 100644 --- a/panels/printers/printer-entry.ui +++ b/panels/printers/printer-entry.ui @@ -20,6 +20,17 @@ + + + True + Printer Details + + + + 1 + 1 + + True diff --git a/panels/printers/printers.gresource.xml b/panels/printers/printers.gresource.xml index 68d9a29b3..ae0c7fa3d 100644 --- a/panels/printers/printers.gresource.xml +++ b/panels/printers/printers.gresource.xml @@ -4,6 +4,7 @@ authentication-dialog.ui jobs-dialog.ui new-printer-dialog.ui + details-dialog.ui options-dialog.ui ppd-selection-dialog.ui printer-entry.ui