GCC Code Coverage Report


Directory: ./
File: panels/printers/pp-details-dialog.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 158 0.0%
Functions: 0 19 0.0%
Branches: 0 55 0.0%

Line Branch Exec Source
1 /*
2 *
3 * Copyright 2016 Red Hat, Inc,
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 * Author: Felipe Borges <feborges@redhat.com>
19 */
20
21 #include "config.h"
22
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <glib/gstdio.h>
31 #include <gtk/gtk.h>
32
33 #include <cups/cups.h>
34 #include <cups/ppd.h>
35
36 #include "pp-details-dialog.h"
37 #include "pp-ppd-selection-dialog.h"
38 #include "pp-printer.h"
39 #include "pp-utils.h"
40
41 struct _PpDetailsDialog {
42 AdwWindow parent_instance;
43
44 GtkBox *driver_buttons;
45 GtkBox *loading_box;
46 GtkLabel *printer_address_label;
47 GtkRevealer *print_name_hint_revealer;
48 GtkEntry *printer_location_entry;
49 GtkLabel *printer_model_label;
50 GtkStack *printer_model_stack;
51 GtkEntry *printer_name_entry;
52 GtkButton *search_for_drivers_button;
53
54 gchar *printer_name;
55 gchar *ppd_file_name;
56 PPDList *all_ppds_list;
57 GCancellable *cancellable;
58
59 /* Dialogs */
60 PpPPDSelectionDialog *pp_ppd_selection_dialog;
61 };
62
63 G_DEFINE_TYPE (PpDetailsDialog, pp_details_dialog, ADW_TYPE_WINDOW)
64
65 static void
66 printer_name_changed (PpDetailsDialog *self)
67 {
68 const gchar *name;
69 g_autofree gchar *title = NULL;
70
71 name = pp_details_dialog_get_printer_name (self);
72
73 if (printer_name_is_valid (name)){
74 /* Translators: This is the title of the dialog. %s is the printer name. */
75 title = g_strdup_printf (_("%s Details"), name);
76 gtk_revealer_set_reveal_child (self->print_name_hint_revealer, FALSE);
77 gtk_window_set_title (GTK_WINDOW (self), title);
78 } else {
79 gtk_revealer_set_reveal_child (self->print_name_hint_revealer, TRUE);
80 }
81 }
82
83 static void set_ppd_cb (const gchar *printer_name, gboolean success, gpointer user_data);
84
85 static void
86 get_ppd_names_cb (PPDName **names,
87 const gchar *printer_name,
88 gboolean cancelled,
89 gpointer user_data)
90 {
91 PpDetailsDialog *self = (PpDetailsDialog*) user_data;
92
93 if (!cancelled)
94 {
95 if (names != NULL)
96 {
97 gtk_label_set_text (self->printer_model_label, names[0]->ppd_display_name);
98 printer_set_ppd_async (printer_name,
99 names[0]->ppd_name,
100 self->cancellable,
101 set_ppd_cb,
102 self);
103 }
104 else
105 {
106 gtk_label_set_text (self->printer_model_label, _("No suitable driver found"));
107 }
108
109 gtk_stack_set_visible_child (self->printer_model_stack, GTK_WIDGET (self->printer_model_label));
110 }
111 }
112
113 static void
114 search_for_drivers (PpDetailsDialog *self)
115 {
116 gtk_stack_set_visible_child (self->printer_model_stack, GTK_WIDGET (self->loading_box));
117 gtk_widget_set_sensitive (GTK_WIDGET (self->search_for_drivers_button), FALSE);
118
119 get_ppd_names_async (self->printer_name,
120 1,
121 self->cancellable,
122 get_ppd_names_cb,
123 self);
124 }
125
126 static void
127 set_ppd_cb (const gchar *printer_name,
128 gboolean success,
129 gpointer user_data)
130 {
131 PpDetailsDialog *self = (PpDetailsDialog*) user_data;
132
133 gtk_label_set_text (GTK_LABEL (self->printer_model_label), self->ppd_file_name);
134 }
135
136 static void
137 ppd_selection_dialog_response_cb (GtkWindow *dialog,
138 gint response_id,
139 gpointer user_data)
140 {
141 PpDetailsDialog *self = (PpDetailsDialog*) user_data;
142
143 if (response_id == GTK_RESPONSE_OK)
144 {
145 g_autofree gchar *ppd_name = NULL;
146
147 ppd_name = pp_ppd_selection_dialog_get_ppd_name (self->pp_ppd_selection_dialog);
148
149 if (self->printer_name && ppd_name)
150 {
151 printer_set_ppd_async (self->printer_name,
152 ppd_name,
153 self->cancellable,
154 set_ppd_cb,
155 self);
156
157 g_clear_pointer (&self->ppd_file_name, g_free);
158 self->ppd_file_name = g_strdup (ppd_name);
159 }
160 }
161
162 gtk_window_destroy (GTK_WINDOW (self->pp_ppd_selection_dialog));
163 self->pp_ppd_selection_dialog = NULL;
164 }
165
166 static void
167 get_all_ppds_async_cb (PPDList *ppds,
168 gpointer user_data)
169 {
170 PpDetailsDialog *self = user_data;
171
172 self->all_ppds_list = ppd_list_copy (ppds);
173
174 if (self->pp_ppd_selection_dialog)
175 pp_ppd_selection_dialog_set_ppd_list (self->pp_ppd_selection_dialog,
176 self->all_ppds_list);
177 }
178
179 static void
180 select_ppd_in_dialog (PpDetailsDialog *self)
181 {
182 g_autofree gchar *device_id = NULL;
183 g_autofree gchar *manufacturer = NULL;
184
185 g_clear_pointer (&self->ppd_file_name, g_free);
186 self->ppd_file_name = g_strdup (cupsGetPPD (self->printer_name));
187
188 if (!self->pp_ppd_selection_dialog)
189 {
190 device_id =
191 get_ppd_attribute (self->ppd_file_name,
192 "1284DeviceID");
193
194 if (device_id)
195 {
196 manufacturer = get_tag_value (device_id, "mfg");
197 if (!manufacturer)
198 manufacturer = get_tag_value (device_id, "manufacturer");
199 }
200
201 if (manufacturer == NULL)
202 {
203 manufacturer =
204 get_ppd_attribute (self->ppd_file_name,
205 "Manufacturer");
206 }
207
208 if (manufacturer == NULL)
209 {
210 manufacturer = g_strdup ("Raw");
211 }
212
213 if (self->all_ppds_list == NULL)
214 {
215 get_all_ppds_async (self->cancellable, get_all_ppds_async_cb, self);
216 }
217
218 self->pp_ppd_selection_dialog = pp_ppd_selection_dialog_new (
219 self->all_ppds_list,
220 manufacturer,
221 ppd_selection_dialog_response_cb,
222 self);
223
224 gtk_window_set_transient_for (GTK_WINDOW (self->pp_ppd_selection_dialog),
225 GTK_WINDOW (self));
226
227 gtk_widget_set_visible (GTK_WIDGET (self->pp_ppd_selection_dialog), TRUE);
228 }
229 }
230
231 static void
232 ppd_file_select_response_cb (PpDetailsDialog *self,
233 gint response_id,
234 GtkDialog *dialog)
235 {
236 if (response_id == GTK_RESPONSE_ACCEPT)
237 {
238 g_autoptr(GFile) file = NULL;
239 g_autofree gchar *ppd_filename = NULL;
240
241 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
242 ppd_filename = g_file_get_path (file);
243
244 if (self->printer_name && ppd_filename)
245 {
246 printer_set_ppd_file_async (self->printer_name,
247 ppd_filename,
248 self->cancellable,
249 set_ppd_cb,
250 self);
251 }
252 }
253
254 gtk_window_destroy (GTK_WINDOW (dialog));
255 }
256
257 static void
258 select_ppd_manually (PpDetailsDialog *self)
259 {
260 GtkFileFilter *filter;
261 GtkWidget *dialog;
262
263 dialog = gtk_file_chooser_dialog_new (_("Select PPD File"),
264 GTK_WINDOW (self),
265 GTK_FILE_CHOOSER_ACTION_OPEN,
266 _("_Cancel"), GTK_RESPONSE_CANCEL,
267 _("_Open"), GTK_RESPONSE_ACCEPT,
268 NULL);
269
270 filter = gtk_file_filter_new ();
271 gtk_file_filter_set_name (filter,
272 _("PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)"));
273 gtk_file_filter_add_pattern (filter, "*.ppd");
274 gtk_file_filter_add_pattern (filter, "*.PPD");
275 gtk_file_filter_add_pattern (filter, "*.ppd.gz");
276 gtk_file_filter_add_pattern (filter, "*.PPD.gz");
277 gtk_file_filter_add_pattern (filter, "*.PPD.GZ");
278
279 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
280
281 gtk_widget_set_visible (dialog, TRUE);
282
283 g_signal_connect_swapped (dialog, "response", G_CALLBACK (ppd_file_select_response_cb), self);
284 }
285
286 static void
287 update_sensitivity (PpDetailsDialog *self,
288 gboolean sensitive)
289 {
290 gtk_widget_set_sensitive (GTK_WIDGET (self->printer_name_entry), sensitive);
291 gtk_widget_set_sensitive (GTK_WIDGET (self->printer_location_entry), sensitive);
292 gtk_widget_set_sensitive (GTK_WIDGET (self->driver_buttons), sensitive);
293 }
294
295 static void
296 pp_details_dialog_init (PpDetailsDialog *self)
297 {
298 gtk_widget_init_template (GTK_WIDGET (self));
299
300 self->cancellable = g_cancellable_new ();
301 }
302
303 static void
304 pp_details_dialog_dispose (GObject *object)
305 {
306 PpDetailsDialog *self = PP_DETAILS_DIALOG (object);
307
308 g_clear_pointer (&self->printer_name, g_free);
309 g_clear_pointer (&self->ppd_file_name, g_free);
310
311 if (self->all_ppds_list != NULL)
312 {
313 ppd_list_free (self->all_ppds_list);
314 self->all_ppds_list = NULL;
315 }
316
317 g_cancellable_cancel (self->cancellable);
318 g_clear_object (&self->cancellable);
319
320 G_OBJECT_CLASS (pp_details_dialog_parent_class)->dispose (object);
321 }
322
323 static void
324 pp_details_dialog_class_init (PpDetailsDialogClass *klass)
325 {
326 GObjectClass *object_class = G_OBJECT_CLASS (klass);
327 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
328
329 object_class->dispose = pp_details_dialog_dispose;
330
331 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/pp-details-dialog.ui");
332
333 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, print_name_hint_revealer);
334 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, driver_buttons);
335 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, loading_box);
336 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_address_label);
337 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_location_entry);
338 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_model_label);
339 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_model_stack);
340 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, printer_name_entry);
341 gtk_widget_class_bind_template_child (widget_class, PpDetailsDialog, search_for_drivers_button);
342
343 gtk_widget_class_bind_template_callback (widget_class, printer_name_changed);
344 gtk_widget_class_bind_template_callback (widget_class, search_for_drivers);
345 gtk_widget_class_bind_template_callback (widget_class, select_ppd_in_dialog);
346 gtk_widget_class_bind_template_callback (widget_class, select_ppd_manually);
347
348 gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL);
349 }
350
351 PpDetailsDialog *
352 pp_details_dialog_new (gchar *printer_name,
353 gchar *printer_location,
354 gchar *printer_address,
355 gchar *printer_make_and_model,
356 gboolean sensitive)
357 {
358 PpDetailsDialog *self;
359 g_autofree gchar *title = NULL;
360 g_autofree gchar *printer_url = NULL;
361
362 self = g_object_new (PP_DETAILS_DIALOG_TYPE, NULL);
363
364 self->printer_name = g_strdup (printer_name);
365 self->ppd_file_name = NULL;
366
367 /* Translators: This is the title of the dialog. %s is the printer name. */
368 title = g_strdup_printf (_("%s Details"), printer_name);
369 gtk_window_set_title (GTK_WINDOW (self), title);
370
371 printer_url = g_strdup_printf ("<a href=\"http://%s:%d\">%s</a>", printer_address, ippPort (), printer_address);
372 gtk_label_set_markup (GTK_LABEL (self->printer_address_label), printer_url);
373
374 gtk_editable_set_text (GTK_EDITABLE (self->printer_name_entry), printer_name);
375 gtk_editable_set_text (GTK_EDITABLE (self->printer_location_entry), printer_location);
376 gtk_label_set_text (GTK_LABEL (self->printer_model_label), printer_make_and_model);
377
378 update_sensitivity (self, sensitive);
379
380 return self;
381 }
382
383 const gchar *
384 pp_details_dialog_get_printer_name (PpDetailsDialog *self)
385 {
386 g_return_val_if_fail (PP_IS_DETAILS_DIALOG (self), NULL);
387 return gtk_editable_get_text (GTK_EDITABLE (self->printer_name_entry));
388 }
389
390 const gchar *
391 pp_details_dialog_get_printer_location (PpDetailsDialog *self)
392 {
393 g_return_val_if_fail (PP_IS_DETAILS_DIALOG (self), NULL);
394 return gtk_editable_get_text (GTK_EDITABLE (self->printer_location_entry));
395 }
396