Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* Copyright 2017 Red Hat, Inc |
3 |
|
|
* |
4 |
|
|
* This program is free software; you can redistribute it and/or modify |
5 |
|
|
* it under the terms of the GNU General Public License as published by |
6 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
7 |
|
|
* (at your option) any later version. |
8 |
|
|
* |
9 |
|
|
* This program is distributed in the hope that it will be useful, |
10 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
|
|
* GNU General Public License for more details. |
13 |
|
|
* |
14 |
|
|
* You should have received a copy of the GNU General Public License |
15 |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 |
|
|
* |
17 |
|
|
* Author: Felipe Borges <felipeborges@gnome.org> |
18 |
|
|
*/ |
19 |
|
|
|
20 |
|
|
#include <config.h> |
21 |
|
|
|
22 |
|
|
#include "pp-printer-entry.h" |
23 |
|
|
#include <gtk/gtk.h> |
24 |
|
|
#include <glib/gi18n-lib.h> |
25 |
|
|
#include <glib/gstdio.h> |
26 |
|
|
|
27 |
|
|
#include "pp-details-dialog.h" |
28 |
|
|
#include "pp-maintenance-command.h" |
29 |
|
|
#include "pp-options-dialog.h" |
30 |
|
|
#include "pp-jobs-dialog.h" |
31 |
|
|
#include "pp-printer.h" |
32 |
|
|
#include "pp-utils.h" |
33 |
|
|
|
34 |
|
|
#define SUPPLY_BAR_HEIGHT 8 |
35 |
|
|
|
36 |
|
|
typedef struct |
37 |
|
|
{ |
38 |
|
|
gchar *marker_names; |
39 |
|
|
gchar *marker_levels; |
40 |
|
|
gchar *marker_colors; |
41 |
|
|
gchar *marker_types; |
42 |
|
|
} InkLevelData; |
43 |
|
|
|
44 |
|
|
struct _PpPrinterEntry |
45 |
|
|
{ |
46 |
|
|
GtkListBoxRow parent; |
47 |
|
|
|
48 |
|
|
gchar *printer_name; |
49 |
|
|
gboolean is_accepting_jobs; |
50 |
|
|
gchar *printer_make_and_model; |
51 |
|
|
gchar *printer_location; |
52 |
|
|
gchar *printer_hostname; |
53 |
|
|
gboolean is_authorized; |
54 |
|
|
gint printer_state; |
55 |
|
|
InkLevelData *inklevel; |
56 |
|
|
|
57 |
|
|
/* Maintenance commands */ |
58 |
|
|
PpMaintenanceCommand *clean_command; |
59 |
|
|
GCancellable *check_clean_heads_cancellable; |
60 |
|
|
|
61 |
|
|
/* Widgets */ |
62 |
|
|
GtkOrientable *header_box; |
63 |
|
|
GtkLabel *printer_status; |
64 |
|
|
GtkLabel *printer_name_label; |
65 |
|
|
GtkLabel *printer_model_label; |
66 |
|
|
GtkLabel *printer_model; |
67 |
|
|
GtkLabel *printer_location_label; |
68 |
|
|
GtkLabel *printer_location_address_label; |
69 |
|
|
GtkLabel *printer_inklevel_label; |
70 |
|
|
GtkFrame *supply_frame; |
71 |
|
|
GtkDrawingArea *supply_drawing_area; |
72 |
|
|
GtkWidget *show_jobs_dialog_button; |
73 |
|
|
GtkBox *printer_error; |
74 |
|
|
GtkLabel *error_status; |
75 |
|
|
|
76 |
|
|
gboolean is_default; |
77 |
|
|
gboolean compact; |
78 |
|
|
|
79 |
|
|
/* Dialogs */ |
80 |
|
|
PpJobsDialog *pp_jobs_dialog; |
81 |
|
|
|
82 |
|
|
GCancellable *get_jobs_cancellable; |
83 |
|
|
}; |
84 |
|
|
|
85 |
|
|
struct _PpPrinterEntryClass |
86 |
|
|
{ |
87 |
|
|
GtkListBoxRowClass parent_class; |
88 |
|
|
|
89 |
|
|
void (*printer_changed) (PpPrinterEntry *printer_entry); |
90 |
|
|
void (*printer_delete) (PpPrinterEntry *printer_entry); |
91 |
|
|
void (*printer_renamed) (PpPrinterEntry *printer_entry, const gchar *new_name); |
92 |
|
|
}; |
93 |
|
|
|
94 |
|
✗ |
G_DEFINE_TYPE (PpPrinterEntry, pp_printer_entry, GTK_TYPE_LIST_BOX_ROW) |
95 |
|
|
|
96 |
|
|
enum { |
97 |
|
|
IS_DEFAULT_PRINTER, |
98 |
|
|
PRINTER_DELETE, |
99 |
|
|
PRINTER_RENAMED, |
100 |
|
|
LAST_SIGNAL, |
101 |
|
|
}; |
102 |
|
|
|
103 |
|
|
static guint signals[LAST_SIGNAL] = { 0 }; |
104 |
|
|
|
105 |
|
|
enum { |
106 |
|
|
PROP_0, |
107 |
|
|
PROP_DEFAULT, |
108 |
|
|
PROP_COMPACT, |
109 |
|
|
}; |
110 |
|
|
|
111 |
|
|
static InkLevelData * |
112 |
|
✗ |
ink_level_data_new (void) |
113 |
|
|
{ |
114 |
|
✗ |
return g_slice_new0 (InkLevelData); |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
static void |
118 |
|
✗ |
ink_level_data_free (InkLevelData *data) |
119 |
|
|
{ |
120 |
|
✗ |
g_clear_pointer (&data->marker_names, g_free); |
121 |
|
✗ |
g_clear_pointer (&data->marker_levels, g_free); |
122 |
|
✗ |
g_clear_pointer (&data->marker_colors, g_free); |
123 |
|
✗ |
g_clear_pointer (&data->marker_types, g_free); |
124 |
|
✗ |
g_slice_free (InkLevelData, data); |
125 |
|
✗ |
} |
126 |
|
|
|
127 |
|
|
static void |
128 |
|
✗ |
pp_printer_entry_init (PpPrinterEntry *self) |
129 |
|
|
{ |
130 |
|
✗ |
gtk_widget_action_set_enabled (GTK_WIDGET (self), "printer.clean-heads", FALSE); |
131 |
|
|
|
132 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
133 |
|
✗ |
self->inklevel = ink_level_data_new (); |
134 |
|
✗ |
} |
135 |
|
|
|
136 |
|
|
typedef struct { |
137 |
|
|
gchar *color; |
138 |
|
|
gchar *type; |
139 |
|
|
gchar *name; |
140 |
|
|
gint level; |
141 |
|
|
} MarkerItem; |
142 |
|
|
|
143 |
|
|
static gint |
144 |
|
✗ |
markers_cmp (gconstpointer a, |
145 |
|
|
gconstpointer b) |
146 |
|
|
{ |
147 |
|
✗ |
MarkerItem *x = (MarkerItem*) a; |
148 |
|
✗ |
MarkerItem *y = (MarkerItem*) b; |
149 |
|
|
|
150 |
|
✗ |
if (x->level < y->level) |
151 |
|
✗ |
return 1; |
152 |
|
✗ |
else if (x->level == y->level) |
153 |
|
✗ |
return 0; |
154 |
|
|
else |
155 |
|
✗ |
return -1; |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
static gchar * |
159 |
|
✗ |
sanitize_printer_model (const gchar *printer_make_and_model) |
160 |
|
|
{ |
161 |
|
✗ |
gchar *breakpoint = NULL, *tmp2 = NULL; |
162 |
|
✗ |
g_autofree gchar *tmp = NULL; |
163 |
|
|
gchar backup; |
164 |
|
✗ |
size_t length = 0; |
165 |
|
✗ |
gchar *forbidden[] = { |
166 |
|
|
"foomatic", |
167 |
|
|
",", |
168 |
|
|
"hpijs", |
169 |
|
|
"hpcups", |
170 |
|
|
"(recommended)", |
171 |
|
|
"postscript (recommended)", |
172 |
|
|
NULL }; |
173 |
|
|
int i; |
174 |
|
|
|
175 |
|
✗ |
tmp = g_ascii_strdown (printer_make_and_model, -1); |
176 |
|
|
|
177 |
|
✗ |
for (i = 0; i < g_strv_length (forbidden); i++) |
178 |
|
|
{ |
179 |
|
✗ |
tmp2 = g_strrstr (tmp, forbidden[i]); |
180 |
|
✗ |
if (breakpoint == NULL || |
181 |
|
✗ |
(tmp2 != NULL && tmp2 < breakpoint)) |
182 |
|
✗ |
breakpoint = tmp2; |
183 |
|
|
} |
184 |
|
|
|
185 |
|
✗ |
if (breakpoint) |
186 |
|
|
{ |
187 |
|
✗ |
backup = *breakpoint; |
188 |
|
✗ |
*breakpoint = '\0'; |
189 |
|
✗ |
length = strlen (tmp); |
190 |
|
✗ |
*breakpoint = backup; |
191 |
|
|
|
192 |
|
✗ |
if (length > 0) |
193 |
|
✗ |
return g_strndup (printer_make_and_model, length); |
194 |
|
|
} |
195 |
|
|
else |
196 |
|
✗ |
return g_strdup (printer_make_and_model); |
197 |
|
|
|
198 |
|
✗ |
return NULL; |
199 |
|
|
} |
200 |
|
|
|
201 |
|
|
static gboolean |
202 |
|
✗ |
supply_level_is_empty (PpPrinterEntry *self) |
203 |
|
|
{ |
204 |
|
✗ |
return !((self->inklevel->marker_levels != NULL) && |
205 |
|
✗ |
(self->inklevel->marker_colors != NULL) && |
206 |
|
✗ |
(self->inklevel->marker_names != NULL) && |
207 |
|
✗ |
(self->inklevel->marker_types != NULL)); |
208 |
|
|
} |
209 |
|
|
|
210 |
|
|
/* To tone down the colors in the supply level bar |
211 |
|
|
* we shade them by darkening the hue. |
212 |
|
|
* |
213 |
|
|
* Obs.: we don't know whether the color is already |
214 |
|
|
* shaded. |
215 |
|
|
* |
216 |
|
|
*/ |
217 |
|
|
static void |
218 |
|
✗ |
tone_down_color (GdkRGBA *color, |
219 |
|
|
gdouble hue_ratio, |
220 |
|
|
gdouble saturation_ratio, |
221 |
|
|
gdouble value_ratio) |
222 |
|
|
{ |
223 |
|
|
gfloat h, s, v; |
224 |
|
|
|
225 |
|
✗ |
gtk_rgb_to_hsv (color->red, color->green, color->blue, |
226 |
|
|
&h, &s, &v); |
227 |
|
✗ |
gtk_hsv_to_rgb (h * hue_ratio, s * saturation_ratio, v * value_ratio, |
228 |
|
|
&color->red, &color->green, &color->blue); |
229 |
|
✗ |
} |
230 |
|
|
|
231 |
|
|
static void |
232 |
|
✗ |
supply_levels_draw_cb (GtkDrawingArea *drawing_area, |
233 |
|
|
cairo_t *cr, |
234 |
|
|
int width, |
235 |
|
|
int height, |
236 |
|
|
gpointer user_data) |
237 |
|
|
{ |
238 |
|
✗ |
PpPrinterEntry *self = PP_PRINTER_ENTRY (user_data); |
239 |
|
|
GtkStyleContext *context; |
240 |
|
✗ |
gboolean is_empty = TRUE; |
241 |
|
✗ |
g_autofree gchar *tooltip_text = NULL; |
242 |
|
|
int i; |
243 |
|
|
|
244 |
|
✗ |
context = gtk_widget_get_style_context (GTK_WIDGET (self->supply_drawing_area)); |
245 |
|
|
|
246 |
|
✗ |
gtk_render_background (context, cr, 0, 0, width, height); |
247 |
|
|
|
248 |
|
✗ |
if (!supply_level_is_empty (self)) |
249 |
|
|
{ |
250 |
|
✗ |
GSList *markers = NULL; |
251 |
|
✗ |
GSList *tmp_list = NULL; |
252 |
|
✗ |
gchar **marker_levelsv = NULL; |
253 |
|
✗ |
gchar **marker_colorsv = NULL; |
254 |
|
✗ |
gchar **marker_namesv = NULL; |
255 |
|
✗ |
gchar **marker_typesv = NULL; |
256 |
|
|
|
257 |
|
✗ |
gtk_style_context_save (context); |
258 |
|
|
|
259 |
|
✗ |
marker_levelsv = g_strsplit (self->inklevel->marker_levels, ",", -1); |
260 |
|
✗ |
marker_colorsv = g_strsplit (self->inklevel->marker_colors, ",", -1); |
261 |
|
✗ |
marker_namesv = g_strsplit (self->inklevel->marker_names, ",", -1); |
262 |
|
✗ |
marker_typesv = g_strsplit (self->inklevel->marker_types, ",", -1); |
263 |
|
|
|
264 |
|
✗ |
if (g_strv_length (marker_levelsv) == g_strv_length (marker_colorsv) && |
265 |
|
✗ |
g_strv_length (marker_colorsv) == g_strv_length (marker_namesv) && |
266 |
|
✗ |
g_strv_length (marker_namesv) == g_strv_length (marker_typesv)) |
267 |
|
|
{ |
268 |
|
✗ |
for (i = 0; i < g_strv_length (marker_levelsv); i++) |
269 |
|
|
{ |
270 |
|
|
MarkerItem *marker; |
271 |
|
|
|
272 |
|
✗ |
if (g_strcmp0 (marker_typesv[i], "ink") == 0 || |
273 |
|
✗ |
g_strcmp0 (marker_typesv[i], "toner") == 0 || |
274 |
|
✗ |
g_strcmp0 (marker_typesv[i], "inkCartridge") == 0 || |
275 |
|
✗ |
g_strcmp0 (marker_typesv[i], "tonerCartridge") == 0) |
276 |
|
|
{ |
277 |
|
✗ |
marker = g_new0 (MarkerItem, 1); |
278 |
|
✗ |
marker->type = g_strdup (marker_typesv[i]); |
279 |
|
✗ |
marker->name = g_strdup (marker_namesv[i]); |
280 |
|
✗ |
marker->color = g_strdup (marker_colorsv[i]); |
281 |
|
✗ |
marker->level = atoi (marker_levelsv[i]); |
282 |
|
|
|
283 |
|
✗ |
markers = g_slist_prepend (markers, marker); |
284 |
|
|
} |
285 |
|
|
} |
286 |
|
|
|
287 |
|
✗ |
markers = g_slist_sort (markers, markers_cmp); |
288 |
|
|
|
289 |
|
✗ |
for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next) |
290 |
|
|
{ |
291 |
|
✗ |
GdkRGBA color = {0.0, 0.0, 0.0, 1.0}; |
292 |
|
|
double display_value; |
293 |
|
|
int value; |
294 |
|
|
|
295 |
|
✗ |
value = ((MarkerItem*) tmp_list->data)->level; |
296 |
|
|
|
297 |
|
✗ |
gdk_rgba_parse (&color, ((MarkerItem*) tmp_list->data)->color); |
298 |
|
✗ |
tone_down_color (&color, 1.0, 0.6, 0.9); |
299 |
|
|
|
300 |
|
✗ |
if (value > 0) |
301 |
|
|
{ |
302 |
|
✗ |
display_value = value / 100.0 * (width - 3.0); |
303 |
|
✗ |
gdk_cairo_set_source_rgba (cr, &color); |
304 |
|
✗ |
cairo_rectangle (cr, 2.0, 2.0, display_value, SUPPLY_BAR_HEIGHT); |
305 |
|
✗ |
cairo_fill (cr); |
306 |
|
|
|
307 |
|
✗ |
tone_down_color (&color, 1.0, 1.0, 0.85); |
308 |
|
✗ |
gdk_cairo_set_source_rgba (cr, &color); |
309 |
|
✗ |
cairo_set_line_width (cr, 1.0); |
310 |
|
✗ |
cairo_rectangle (cr, 1.5, 1.5, display_value, SUPPLY_BAR_HEIGHT + 1); |
311 |
|
✗ |
cairo_stroke (cr); |
312 |
|
|
|
313 |
|
✗ |
is_empty = FALSE; |
314 |
|
|
} |
315 |
|
|
|
316 |
|
✗ |
if (tooltip_text) |
317 |
|
|
{ |
318 |
|
✗ |
g_autofree gchar *old_tooltip_text = g_steal_pointer (&tooltip_text); |
319 |
|
✗ |
tooltip_text = g_strdup_printf ("%s\n%s", |
320 |
|
|
old_tooltip_text, |
321 |
|
✗ |
((MarkerItem*) tmp_list->data)->name); |
322 |
|
|
} |
323 |
|
|
else |
324 |
|
✗ |
tooltip_text = g_strdup_printf ("%s", |
325 |
|
✗ |
((MarkerItem*) tmp_list->data)->name); |
326 |
|
|
} |
327 |
|
|
|
328 |
|
✗ |
gtk_render_frame (context, cr, 1, 1, width - 1, SUPPLY_BAR_HEIGHT); |
329 |
|
|
|
330 |
|
✗ |
for (tmp_list = markers; tmp_list; tmp_list = tmp_list->next) |
331 |
|
|
{ |
332 |
|
✗ |
g_free (((MarkerItem*) tmp_list->data)->name); |
333 |
|
✗ |
g_free (((MarkerItem*) tmp_list->data)->type); |
334 |
|
✗ |
g_free (((MarkerItem*) tmp_list->data)->color); |
335 |
|
|
} |
336 |
|
✗ |
g_slist_free_full (markers, g_free); |
337 |
|
|
} |
338 |
|
|
|
339 |
|
✗ |
gtk_style_context_restore (context); |
340 |
|
|
|
341 |
|
✗ |
if (tooltip_text) |
342 |
|
|
{ |
343 |
|
✗ |
gtk_widget_set_tooltip_text (GTK_WIDGET (self->supply_drawing_area), tooltip_text); |
344 |
|
|
} |
345 |
|
|
else |
346 |
|
|
{ |
347 |
|
✗ |
gtk_widget_set_tooltip_text (GTK_WIDGET (self->supply_drawing_area), NULL); |
348 |
|
✗ |
gtk_widget_set_has_tooltip (GTK_WIDGET (self->supply_drawing_area), FALSE); |
349 |
|
|
} |
350 |
|
|
} |
351 |
|
|
|
352 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_inklevel_label), !is_empty); |
353 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->supply_frame), !is_empty); |
354 |
|
✗ |
} |
355 |
|
|
|
356 |
|
|
static void |
357 |
|
✗ |
on_printer_rename_cb (GObject *source_object, |
358 |
|
|
GAsyncResult *result, |
359 |
|
|
gpointer user_data) |
360 |
|
|
{ |
361 |
|
✗ |
PpPrinterEntry *self = user_data; |
362 |
|
|
|
363 |
|
✗ |
if (!pp_printer_rename_finish (PP_PRINTER (source_object), result, NULL)) |
364 |
|
✗ |
return; |
365 |
|
|
|
366 |
|
✗ |
g_signal_emit_by_name (self, "printer-renamed", pp_printer_get_name (PP_PRINTER (source_object))); |
367 |
|
|
} |
368 |
|
|
|
369 |
|
|
static gboolean |
370 |
|
✗ |
show_printer_details_response_cb (PpPrinterEntry *self, |
371 |
|
|
PpDetailsDialog *dialog) |
372 |
|
|
{ |
373 |
|
|
const gchar *new_name; |
374 |
|
|
const gchar *new_location; |
375 |
|
|
|
376 |
|
✗ |
new_location = pp_details_dialog_get_printer_location (dialog); |
377 |
|
✗ |
if (g_strcmp0 (self->printer_location, new_location) != 0) |
378 |
|
✗ |
printer_set_location (self->printer_name, new_location); |
379 |
|
|
|
380 |
|
✗ |
new_name = pp_details_dialog_get_printer_name (dialog); |
381 |
|
✗ |
if (g_strcmp0 (self->printer_name, new_name) != 0 && printer_name_is_valid (new_name)) |
382 |
|
|
{ |
383 |
|
✗ |
g_autoptr(PpPrinter) printer = pp_printer_new (self->printer_name); |
384 |
|
|
|
385 |
|
✗ |
pp_printer_rename_async (printer, |
386 |
|
|
new_name, |
387 |
|
|
NULL, |
388 |
|
|
on_printer_rename_cb, |
389 |
|
|
self); |
390 |
|
|
} |
391 |
|
|
|
392 |
|
✗ |
g_signal_emit_by_name (self, "printer-changed"); |
393 |
|
|
|
394 |
|
✗ |
return GDK_EVENT_PROPAGATE; |
395 |
|
|
} |
396 |
|
|
|
397 |
|
|
static void |
398 |
|
✗ |
printer_details_cb (PpPrinterEntry *self) |
399 |
|
|
{ |
400 |
|
✗ |
PpDetailsDialog *dialog = pp_details_dialog_new (self->printer_name, |
401 |
|
|
self->printer_location, |
402 |
|
|
self->printer_hostname, |
403 |
|
|
self->printer_make_and_model, |
404 |
|
|
self->is_authorized); |
405 |
|
|
|
406 |
|
✗ |
gtk_window_set_transient_for (GTK_WINDOW (dialog), |
407 |
|
✗ |
GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)))); |
408 |
|
|
|
409 |
|
✗ |
g_signal_connect_swapped (dialog, "close-request", G_CALLBACK (show_printer_details_response_cb), self); |
410 |
|
|
|
411 |
|
✗ |
gtk_window_present (GTK_WINDOW (dialog)); |
412 |
|
✗ |
} |
413 |
|
|
|
414 |
|
|
static void |
415 |
|
✗ |
printer_options_cb (PpPrinterEntry *self) |
416 |
|
|
{ |
417 |
|
|
PpOptionsDialog *dialog; |
418 |
|
|
|
419 |
|
✗ |
dialog = pp_options_dialog_new (self->printer_name, self->is_authorized); |
420 |
|
|
|
421 |
|
✗ |
gtk_window_set_transient_for (GTK_WINDOW (dialog), |
422 |
|
✗ |
GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)))); |
423 |
|
|
|
424 |
|
✗ |
gtk_window_present (GTK_WINDOW (dialog)); |
425 |
|
✗ |
} |
426 |
|
|
|
427 |
|
|
static void |
428 |
|
✗ |
set_as_default_printer (PpPrinterEntry *self) |
429 |
|
|
{ |
430 |
|
✗ |
if (self->is_default) |
431 |
|
✗ |
return; |
432 |
|
|
|
433 |
|
✗ |
printer_set_default (self->printer_name); |
434 |
|
|
|
435 |
|
✗ |
self->is_default = TRUE; |
436 |
|
|
|
437 |
|
✗ |
g_object_notify (G_OBJECT (self), "default"); |
438 |
|
|
|
439 |
|
✗ |
g_signal_emit_by_name (self, "printer-changed"); |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
static void |
443 |
|
✗ |
check_clean_heads_maintenance_command_cb (GObject *source_object, |
444 |
|
|
GAsyncResult *res, |
445 |
|
|
gpointer user_data) |
446 |
|
|
{ |
447 |
|
✗ |
PpPrinterEntry *self = user_data; |
448 |
|
✗ |
gboolean is_supported = FALSE; |
449 |
|
✗ |
g_autoptr(GError) error = NULL; |
450 |
|
|
|
451 |
|
✗ |
is_supported = pp_maintenance_command_is_supported_finish (PP_MAINTENANCE_COMMAND (source_object), res, &error); |
452 |
|
✗ |
if (error != NULL) |
453 |
|
|
{ |
454 |
|
✗ |
g_debug ("Could not check 'Clean' maintenance command: %s", error->message); |
455 |
|
✗ |
return; |
456 |
|
|
} |
457 |
|
|
|
458 |
|
✗ |
if (is_supported) |
459 |
|
|
{ |
460 |
|
✗ |
gtk_widget_action_set_enabled (GTK_WIDGET (self), "printer.clean-heads", TRUE); |
461 |
|
|
} |
462 |
|
|
} |
463 |
|
|
|
464 |
|
|
static void |
465 |
|
✗ |
check_clean_heads_maintenance_command (PpPrinterEntry *self) |
466 |
|
|
{ |
467 |
|
✗ |
if (self->clean_command == NULL) |
468 |
|
✗ |
return; |
469 |
|
|
|
470 |
|
✗ |
g_object_ref (self->clean_command); |
471 |
|
✗ |
self->check_clean_heads_cancellable = g_cancellable_new (); |
472 |
|
|
|
473 |
|
✗ |
pp_maintenance_command_is_supported_async (self->clean_command, |
474 |
|
|
self->check_clean_heads_cancellable, |
475 |
|
|
check_clean_heads_maintenance_command_cb, |
476 |
|
|
self); |
477 |
|
|
} |
478 |
|
|
|
479 |
|
|
static void |
480 |
|
✗ |
clean_heads_maintenance_command_cb (GObject *source_object, |
481 |
|
|
GAsyncResult *res, |
482 |
|
|
gpointer user_data) |
483 |
|
|
{ |
484 |
|
✗ |
PpPrinterEntry *self = user_data; |
485 |
|
✗ |
g_autoptr(GError) error = NULL; |
486 |
|
|
|
487 |
|
✗ |
if (!pp_maintenance_command_execute_finish (PP_MAINTENANCE_COMMAND (source_object), res, &error)) |
488 |
|
✗ |
g_warning ("Error cleaning print heads for %s: %s", self->printer_name, error->message); |
489 |
|
✗ |
} |
490 |
|
|
|
491 |
|
|
static void |
492 |
|
✗ |
printer_clean_heads_cb (PpPrinterEntry *self) |
493 |
|
|
{ |
494 |
|
✗ |
if (self->clean_command == NULL) |
495 |
|
✗ |
return; |
496 |
|
|
|
497 |
|
✗ |
g_object_ref (self->clean_command); |
498 |
|
✗ |
pp_maintenance_command_execute_async (self->clean_command, |
499 |
|
|
NULL, |
500 |
|
|
clean_heads_maintenance_command_cb, |
501 |
|
|
self); |
502 |
|
|
} |
503 |
|
|
|
504 |
|
|
static void |
505 |
|
✗ |
printer_remove_cb (PpPrinterEntry *self) |
506 |
|
|
{ |
507 |
|
✗ |
g_signal_emit_by_name (self, "printer-delete"); |
508 |
|
✗ |
} |
509 |
|
|
|
510 |
|
|
static void |
511 |
|
✗ |
get_jobs_cb (GObject *source_object, |
512 |
|
|
GAsyncResult *result, |
513 |
|
|
gpointer user_data) |
514 |
|
|
{ |
515 |
|
✗ |
PpPrinterEntry *self = user_data; |
516 |
|
✗ |
g_autoptr(GError) error = NULL; |
517 |
|
✗ |
g_autoptr(GPtrArray) jobs = NULL; |
518 |
|
✗ |
g_autofree gchar *button_label = NULL; |
519 |
|
|
|
520 |
|
✗ |
jobs = pp_printer_get_jobs_finish (PP_PRINTER (source_object), result, &error); |
521 |
|
|
|
522 |
|
✗ |
if (error != NULL) |
523 |
|
|
{ |
524 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
525 |
|
|
{ |
526 |
|
✗ |
g_warning ("Could not get jobs: %s", error->message); |
527 |
|
|
} |
528 |
|
|
|
529 |
|
✗ |
return; |
530 |
|
|
} |
531 |
|
|
|
532 |
|
✗ |
if (jobs->len == 0) |
533 |
|
|
{ |
534 |
|
|
/* Translators: This is the label of the button that opens the Jobs Dialog. */ |
535 |
|
✗ |
button_label = g_strdup (_("No Active Jobs")); |
536 |
|
|
} |
537 |
|
|
else |
538 |
|
|
{ |
539 |
|
|
/* Translators: This is the label of the button that opens the Jobs Dialog. */ |
540 |
|
✗ |
button_label = g_strdup_printf (ngettext ("%u Job", "%u Jobs", jobs->len), jobs->len); |
541 |
|
|
} |
542 |
|
|
|
543 |
|
✗ |
gtk_button_set_label (GTK_BUTTON (self->show_jobs_dialog_button), button_label); |
544 |
|
✗ |
gtk_widget_set_sensitive (self->show_jobs_dialog_button, jobs->len > 0); |
545 |
|
|
|
546 |
|
✗ |
if (self->pp_jobs_dialog != NULL) |
547 |
|
|
{ |
548 |
|
✗ |
pp_jobs_dialog_update (self->pp_jobs_dialog); |
549 |
|
|
} |
550 |
|
|
|
551 |
|
✗ |
g_clear_object (&self->get_jobs_cancellable); |
552 |
|
|
} |
553 |
|
|
|
554 |
|
|
void |
555 |
|
✗ |
pp_printer_entry_update_jobs_count (PpPrinterEntry *self) |
556 |
|
|
{ |
557 |
|
✗ |
g_autoptr(PpPrinter) printer = NULL; |
558 |
|
|
|
559 |
|
✗ |
g_cancellable_cancel (self->get_jobs_cancellable); |
560 |
|
✗ |
g_clear_object (&self->get_jobs_cancellable); |
561 |
|
|
|
562 |
|
✗ |
self->get_jobs_cancellable = g_cancellable_new (); |
563 |
|
|
|
564 |
|
✗ |
printer = pp_printer_new (self->printer_name); |
565 |
|
✗ |
pp_printer_get_jobs_async (printer, |
566 |
|
|
TRUE, |
567 |
|
|
CUPS_WHICHJOBS_ACTIVE, |
568 |
|
|
self->get_jobs_cancellable, |
569 |
|
|
get_jobs_cb, |
570 |
|
|
self); |
571 |
|
✗ |
} |
572 |
|
|
|
573 |
|
|
static gboolean |
574 |
|
✗ |
jobs_dialog_close_request_cb (PpPrinterEntry *self) |
575 |
|
|
{ |
576 |
|
✗ |
if (self->pp_jobs_dialog != NULL) |
577 |
|
|
{ |
578 |
|
✗ |
gtk_window_destroy (GTK_WINDOW (self->pp_jobs_dialog)); |
579 |
|
✗ |
self->pp_jobs_dialog = NULL; |
580 |
|
|
} |
581 |
|
|
|
582 |
|
✗ |
return GDK_EVENT_STOP; |
583 |
|
|
} |
584 |
|
|
|
585 |
|
|
void |
586 |
|
✗ |
pp_printer_entry_show_jobs_dialog (PpPrinterEntry *self) |
587 |
|
|
{ |
588 |
|
✗ |
if (self->pp_jobs_dialog == NULL) |
589 |
|
|
{ |
590 |
|
✗ |
self->pp_jobs_dialog = pp_jobs_dialog_new (self->printer_name); |
591 |
|
✗ |
g_signal_connect_object (self->pp_jobs_dialog, "close-request", G_CALLBACK (jobs_dialog_close_request_cb), self, G_CONNECT_SWAPPED); |
592 |
|
✗ |
gtk_window_set_transient_for (GTK_WINDOW (self->pp_jobs_dialog), GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)))); |
593 |
|
✗ |
gtk_window_present (GTK_WINDOW (self->pp_jobs_dialog)); |
594 |
|
|
} |
595 |
|
✗ |
} |
596 |
|
|
|
597 |
|
|
void |
598 |
|
✗ |
pp_printer_entry_authenticate_jobs (PpPrinterEntry *self) |
599 |
|
|
{ |
600 |
|
✗ |
pp_printer_entry_show_jobs_dialog (self); |
601 |
|
✗ |
pp_jobs_dialog_authenticate_jobs (self->pp_jobs_dialog); |
602 |
|
✗ |
} |
603 |
|
|
|
604 |
|
|
static void |
605 |
|
✗ |
show_jobs_dialog (GtkButton *button, |
606 |
|
|
gpointer user_data) |
607 |
|
|
{ |
608 |
|
✗ |
pp_printer_entry_show_jobs_dialog (PP_PRINTER_ENTRY (user_data)); |
609 |
|
✗ |
} |
610 |
|
|
|
611 |
|
|
enum |
612 |
|
|
{ |
613 |
|
|
PRINTER_READY = 3, |
614 |
|
|
PRINTER_PROCESSING, |
615 |
|
|
PRINTER_STOPPED |
616 |
|
|
}; |
617 |
|
|
|
618 |
|
|
static void |
619 |
|
✗ |
restart_printer (GtkButton *button, |
620 |
|
|
PpPrinterEntry *self) |
621 |
|
|
{ |
622 |
|
✗ |
if (self->printer_state == PRINTER_STOPPED) |
623 |
|
✗ |
printer_set_enabled (self->printer_name, TRUE); |
624 |
|
|
|
625 |
|
✗ |
if (!self->is_accepting_jobs) |
626 |
|
✗ |
printer_set_accepting_jobs (self->printer_name, TRUE, NULL); |
627 |
|
|
|
628 |
|
✗ |
g_signal_emit_by_name (self, "printer-changed"); |
629 |
|
✗ |
} |
630 |
|
|
|
631 |
|
|
GSList * |
632 |
|
✗ |
pp_printer_entry_get_size_group_widgets (PpPrinterEntry *self) |
633 |
|
|
{ |
634 |
|
✗ |
GSList *widgets = NULL; |
635 |
|
|
|
636 |
|
✗ |
widgets = g_slist_prepend (widgets, self->printer_location_label); |
637 |
|
✗ |
widgets = g_slist_prepend (widgets, self->printer_model_label); |
638 |
|
✗ |
widgets = g_slist_prepend (widgets, self->printer_inklevel_label); |
639 |
|
|
|
640 |
|
✗ |
return widgets; |
641 |
|
|
} |
642 |
|
|
|
643 |
|
|
PpPrinterEntry * |
644 |
|
✗ |
pp_printer_entry_new (cups_dest_t printer, |
645 |
|
|
gboolean is_authorized) |
646 |
|
|
{ |
647 |
|
|
PpPrinterEntry *self; |
648 |
|
|
|
649 |
|
✗ |
self = g_object_new (PP_PRINTER_ENTRY_TYPE, NULL); |
650 |
|
|
|
651 |
|
✗ |
self->printer_name = g_strdup (printer.name); |
652 |
|
|
|
653 |
|
✗ |
self->clean_command = pp_maintenance_command_new (self->printer_name, |
654 |
|
|
"Clean", |
655 |
|
|
"all", |
656 |
|
|
/* Translators: Name of job which makes printer to clean its heads */ |
657 |
|
|
_("Clean print heads")); |
658 |
|
✗ |
check_clean_heads_maintenance_command (self); |
659 |
|
|
|
660 |
|
✗ |
gtk_drawing_area_set_draw_func (self->supply_drawing_area, |
661 |
|
|
supply_levels_draw_cb, |
662 |
|
|
self, |
663 |
|
|
NULL); |
664 |
|
|
|
665 |
|
✗ |
pp_printer_entry_update (self, printer, is_authorized); |
666 |
|
|
|
667 |
|
✗ |
return self; |
668 |
|
|
} |
669 |
|
|
|
670 |
|
|
const gchar * |
671 |
|
✗ |
pp_printer_entry_get_name (PpPrinterEntry *self) |
672 |
|
|
{ |
673 |
|
✗ |
g_return_val_if_fail (PP_IS_PRINTER_ENTRY (self), NULL); |
674 |
|
✗ |
return self->printer_name; |
675 |
|
|
} |
676 |
|
|
|
677 |
|
|
const gchar * |
678 |
|
✗ |
pp_printer_entry_get_location (PpPrinterEntry *self) |
679 |
|
|
{ |
680 |
|
✗ |
g_return_val_if_fail (PP_IS_PRINTER_ENTRY (self), NULL); |
681 |
|
✗ |
return self->printer_location; |
682 |
|
|
} |
683 |
|
|
|
684 |
|
|
void |
685 |
|
✗ |
pp_printer_entry_update (PpPrinterEntry *self, |
686 |
|
|
cups_dest_t printer, |
687 |
|
|
gboolean is_authorized) |
688 |
|
|
{ |
689 |
|
✗ |
cups_ptype_t printer_type = 0; |
690 |
|
✗ |
gboolean is_accepting_jobs = TRUE; |
691 |
|
|
gboolean ink_supply_is_empty; |
692 |
|
✗ |
g_autofree gchar *instance = NULL; |
693 |
|
✗ |
const gchar *printer_uri = NULL; |
694 |
|
✗ |
const gchar *device_uri = NULL; |
695 |
|
✗ |
const gchar *location = NULL; |
696 |
|
✗ |
const gchar *printer_make_and_model = NULL; |
697 |
|
✗ |
const gchar *reason = NULL; |
698 |
|
✗ |
gchar **printer_reasons = NULL; |
699 |
|
✗ |
g_autofree gchar *status = NULL; |
700 |
|
✗ |
g_autofree gchar *printer_status = NULL; |
701 |
|
|
int i, j; |
702 |
|
|
static const char * const reasons[] = |
703 |
|
|
{ |
704 |
|
|
"toner-low", |
705 |
|
|
"toner-empty", |
706 |
|
|
"developer-low", |
707 |
|
|
"developer-empty", |
708 |
|
|
"marker-supply-low", |
709 |
|
|
"marker-supply-empty", |
710 |
|
|
"cover-open", |
711 |
|
|
"door-open", |
712 |
|
|
"media-low", |
713 |
|
|
"media-empty", |
714 |
|
|
"offline", |
715 |
|
|
"paused", |
716 |
|
|
"marker-waste-almost-full", |
717 |
|
|
"marker-waste-full", |
718 |
|
|
"opc-near-eol", |
719 |
|
|
"opc-life-over" |
720 |
|
|
}; |
721 |
|
|
static const char * statuses[] = |
722 |
|
|
{ |
723 |
|
|
/* Translators: The printer is low on toner */ |
724 |
|
|
N_("Low on toner"), |
725 |
|
|
/* Translators: The printer has no toner left */ |
726 |
|
|
N_("Out of toner"), |
727 |
|
|
/* Translators: "Developer" is a chemical for photo development, |
728 |
|
|
* http://en.wikipedia.org/wiki/Photographic_developer */ |
729 |
|
|
N_("Low on developer"), |
730 |
|
|
/* Translators: "Developer" is a chemical for photo development, |
731 |
|
|
* http://en.wikipedia.org/wiki/Photographic_developer */ |
732 |
|
|
N_("Out of developer"), |
733 |
|
|
/* Translators: "marker" is one color bin of the printer */ |
734 |
|
|
N_("Low on a marker supply"), |
735 |
|
|
/* Translators: "marker" is one color bin of the printer */ |
736 |
|
|
N_("Out of a marker supply"), |
737 |
|
|
/* Translators: One or more covers on the printer are open */ |
738 |
|
|
N_("Open cover"), |
739 |
|
|
/* Translators: One or more doors on the printer are open */ |
740 |
|
|
N_("Open door"), |
741 |
|
|
/* Translators: At least one input tray is low on media */ |
742 |
|
|
N_("Low on paper"), |
743 |
|
|
/* Translators: At least one input tray is empty */ |
744 |
|
|
N_("Out of paper"), |
745 |
|
|
/* Translators: The printer is offline */ |
746 |
|
|
NC_("printer state", "Offline"), |
747 |
|
|
/* Translators: Someone has stopped the Printer */ |
748 |
|
|
NC_("printer state", "Stopped"), |
749 |
|
|
/* Translators: The printer marker supply waste receptacle is almost full */ |
750 |
|
|
N_("Waste receptacle almost full"), |
751 |
|
|
/* Translators: The printer marker supply waste receptacle is full */ |
752 |
|
|
N_("Waste receptacle full"), |
753 |
|
|
/* Translators: Optical photo conductors are used in laser printers */ |
754 |
|
|
N_("The optical photo conductor is near end of life"), |
755 |
|
|
/* Translators: Optical photo conductors are used in laser printers */ |
756 |
|
|
N_("The optical photo conductor is no longer functioning") |
757 |
|
|
}; |
758 |
|
|
|
759 |
|
✗ |
if (printer.instance) |
760 |
|
|
{ |
761 |
|
✗ |
instance = g_strdup_printf ("%s / %s", printer.name, printer.instance); |
762 |
|
|
} |
763 |
|
|
else |
764 |
|
|
{ |
765 |
|
✗ |
instance = g_strdup (printer.name); |
766 |
|
|
} |
767 |
|
|
|
768 |
|
✗ |
self->printer_state = PRINTER_READY; |
769 |
|
|
|
770 |
|
✗ |
for (i = 0; i < printer.num_options; i++) |
771 |
|
|
{ |
772 |
|
✗ |
if (g_strcmp0 (printer.options[i].name, "device-uri") == 0) |
773 |
|
✗ |
device_uri = printer.options[i].value; |
774 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-uri-supported") == 0) |
775 |
|
✗ |
printer_uri = printer.options[i].value; |
776 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-type") == 0) |
777 |
|
✗ |
printer_type = atoi (printer.options[i].value); |
778 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-location") == 0) |
779 |
|
✗ |
location = printer.options[i].value; |
780 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-state-reasons") == 0) |
781 |
|
✗ |
reason = printer.options[i].value; |
782 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "marker-names") == 0) |
783 |
|
|
{ |
784 |
|
✗ |
g_free (self->inklevel->marker_names); |
785 |
|
✗ |
self->inklevel->marker_names = g_strcompress (g_strdup (printer.options[i].value)); |
786 |
|
|
} |
787 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "marker-levels") == 0) |
788 |
|
|
{ |
789 |
|
✗ |
g_free (self->inklevel->marker_levels); |
790 |
|
✗ |
self->inklevel->marker_levels = g_strdup (printer.options[i].value); |
791 |
|
|
} |
792 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "marker-colors") == 0) |
793 |
|
|
{ |
794 |
|
✗ |
g_free (self->inklevel->marker_colors); |
795 |
|
✗ |
self->inklevel->marker_colors = g_strdup (printer.options[i].value); |
796 |
|
|
} |
797 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "marker-types") == 0) |
798 |
|
|
{ |
799 |
|
✗ |
g_free (self->inklevel->marker_types); |
800 |
|
✗ |
self->inklevel->marker_types = g_strdup (printer.options[i].value); |
801 |
|
|
} |
802 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-make-and-model") == 0) |
803 |
|
✗ |
printer_make_and_model = printer.options[i].value; |
804 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-state") == 0) |
805 |
|
✗ |
self->printer_state = atoi (printer.options[i].value); |
806 |
|
✗ |
else if (g_strcmp0 (printer.options[i].name, "printer-is-accepting-jobs") == 0) |
807 |
|
|
{ |
808 |
|
✗ |
if (g_strcmp0 (printer.options[i].value, "true") == 0) |
809 |
|
✗ |
is_accepting_jobs = TRUE; |
810 |
|
|
else |
811 |
|
✗ |
is_accepting_jobs = FALSE; |
812 |
|
|
} |
813 |
|
|
} |
814 |
|
|
|
815 |
|
|
/* Find the first of the most severe reasons |
816 |
|
|
* and show it in the status field |
817 |
|
|
*/ |
818 |
|
✗ |
if (reason && !g_str_equal (reason, "none")) |
819 |
|
|
{ |
820 |
|
✗ |
int errors = 0, warnings = 0, reports = 0; |
821 |
|
✗ |
int error_index = -1, warning_index = -1, report_index = -1; |
822 |
|
|
|
823 |
|
✗ |
printer_reasons = g_strsplit (reason, ",", -1); |
824 |
|
✗ |
for (i = 0; i < g_strv_length (printer_reasons); i++) |
825 |
|
|
{ |
826 |
|
✗ |
for (j = 0; j < G_N_ELEMENTS (reasons); j++) |
827 |
|
✗ |
if (strncmp (printer_reasons[i], reasons[j], strlen (reasons[j])) == 0) |
828 |
|
|
{ |
829 |
|
✗ |
if (g_str_has_suffix (printer_reasons[i], "-report")) |
830 |
|
|
{ |
831 |
|
✗ |
if (reports == 0) |
832 |
|
✗ |
report_index = j; |
833 |
|
✗ |
reports++; |
834 |
|
|
} |
835 |
|
✗ |
else if (g_str_has_suffix (printer_reasons[i], "-warning")) |
836 |
|
|
{ |
837 |
|
✗ |
if (warnings == 0) |
838 |
|
✗ |
warning_index = j; |
839 |
|
✗ |
warnings++; |
840 |
|
|
} |
841 |
|
|
else |
842 |
|
|
{ |
843 |
|
✗ |
if (errors == 0) |
844 |
|
✗ |
error_index = j; |
845 |
|
✗ |
errors++; |
846 |
|
|
} |
847 |
|
|
} |
848 |
|
|
} |
849 |
|
✗ |
g_strfreev (printer_reasons); |
850 |
|
|
|
851 |
|
✗ |
if (error_index >= 0) |
852 |
|
✗ |
status = g_strdup (_(statuses[error_index])); |
853 |
|
✗ |
else if (warning_index >= 0) |
854 |
|
✗ |
status = g_strdup (_(statuses[warning_index])); |
855 |
|
✗ |
else if (report_index >= 0) |
856 |
|
✗ |
status = g_strdup (_(statuses[report_index])); |
857 |
|
|
} |
858 |
|
|
|
859 |
|
✗ |
if ((self->printer_state == PRINTER_STOPPED || !is_accepting_jobs) && |
860 |
|
✗ |
status != NULL && status[0] != '\0') |
861 |
|
|
{ |
862 |
|
✗ |
gtk_label_set_label (self->error_status, status); |
863 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_error), TRUE); |
864 |
|
|
} |
865 |
|
|
else |
866 |
|
|
{ |
867 |
|
✗ |
gtk_label_set_label (self->error_status, ""); |
868 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_error), FALSE); |
869 |
|
|
} |
870 |
|
|
|
871 |
|
✗ |
switch (self->printer_state) |
872 |
|
|
{ |
873 |
|
✗ |
case PRINTER_READY: |
874 |
|
✗ |
if (is_accepting_jobs) |
875 |
|
|
{ |
876 |
|
|
/* Translators: Printer's state (can start new job without waiting) */ |
877 |
|
✗ |
printer_status = g_strdup ( C_("printer state", "Ready")); |
878 |
|
|
} |
879 |
|
|
else |
880 |
|
|
{ |
881 |
|
|
/* Translators: Printer's state (printer is ready but doesn't accept new jobs) */ |
882 |
|
✗ |
printer_status = g_strdup ( C_("printer state", "Does not accept jobs")); |
883 |
|
|
} |
884 |
|
✗ |
break; |
885 |
|
✗ |
case PRINTER_PROCESSING: |
886 |
|
|
/* Translators: Printer's state (jobs are processing) */ |
887 |
|
✗ |
printer_status = g_strdup ( C_("printer state", "Processing")); |
888 |
|
✗ |
break; |
889 |
|
✗ |
case PRINTER_STOPPED: |
890 |
|
|
/* Translators: Printer's state (no jobs can be processed) */ |
891 |
|
✗ |
printer_status = g_strdup ( C_("printer state", "Stopped")); |
892 |
|
✗ |
break; |
893 |
|
|
} |
894 |
|
|
|
895 |
|
✗ |
g_free (self->printer_location); |
896 |
|
✗ |
self->printer_location = g_strdup (location); |
897 |
|
|
|
898 |
|
✗ |
self->is_accepting_jobs = is_accepting_jobs; |
899 |
|
✗ |
self->is_authorized = is_authorized; |
900 |
|
|
|
901 |
|
✗ |
g_free (self->printer_hostname); |
902 |
|
✗ |
self->printer_hostname = printer_get_hostname (printer_type, device_uri, printer_uri); |
903 |
|
|
|
904 |
|
✗ |
gtk_label_set_text (self->printer_status, printer_status); |
905 |
|
✗ |
gtk_label_set_text (self->printer_name_label, instance); |
906 |
|
✗ |
self->is_default = printer.is_default; |
907 |
|
✗ |
g_object_notify (G_OBJECT (self), "default"); |
908 |
|
|
|
909 |
|
✗ |
self->printer_make_and_model = sanitize_printer_model (printer_make_and_model); |
910 |
|
|
|
911 |
|
✗ |
if (self->printer_make_and_model == NULL || self->printer_make_and_model[0] == '\0') |
912 |
|
|
{ |
913 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_model_label), FALSE); |
914 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_model), FALSE); |
915 |
|
|
} |
916 |
|
|
else |
917 |
|
|
{ |
918 |
|
✗ |
gtk_label_set_text (self->printer_model, self->printer_make_and_model); |
919 |
|
|
} |
920 |
|
|
|
921 |
|
✗ |
if (location != NULL && location[0] == '\0') |
922 |
|
|
{ |
923 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_location_label), FALSE); |
924 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_location_address_label), FALSE); |
925 |
|
|
} |
926 |
|
|
else |
927 |
|
|
{ |
928 |
|
✗ |
gtk_label_set_text (self->printer_location_address_label, location); |
929 |
|
|
} |
930 |
|
|
|
931 |
|
✗ |
ink_supply_is_empty = supply_level_is_empty (self); |
932 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->printer_inklevel_label), !ink_supply_is_empty); |
933 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->supply_frame), !ink_supply_is_empty); |
934 |
|
|
|
935 |
|
✗ |
pp_printer_entry_update_jobs_count (self); |
936 |
|
|
|
937 |
|
✗ |
gtk_widget_action_set_enabled (GTK_WIDGET (self), "printer.default", self->is_authorized); |
938 |
|
✗ |
gtk_widget_action_set_enabled (GTK_WIDGET (self), "printer.remove", self->is_authorized); |
939 |
|
✗ |
} |
940 |
|
|
|
941 |
|
|
static void |
942 |
|
✗ |
set_compact (PpPrinterEntry *self, |
943 |
|
|
gboolean compact) |
944 |
|
|
{ |
945 |
|
✗ |
compact = !!compact; |
946 |
|
|
|
947 |
|
✗ |
if (self->compact == compact) |
948 |
|
✗ |
return; |
949 |
|
|
|
950 |
|
✗ |
self->compact = compact; |
951 |
|
|
|
952 |
|
✗ |
if (compact) |
953 |
|
✗ |
gtk_orientable_set_orientation (self->header_box, GTK_ORIENTATION_VERTICAL); |
954 |
|
|
else |
955 |
|
✗ |
gtk_orientable_set_orientation (self->header_box, GTK_ORIENTATION_HORIZONTAL); |
956 |
|
|
} |
957 |
|
|
|
958 |
|
|
static void |
959 |
|
✗ |
pp_printer_entry_dispose (GObject *object) |
960 |
|
|
{ |
961 |
|
✗ |
PpPrinterEntry *self = PP_PRINTER_ENTRY (object); |
962 |
|
|
|
963 |
|
✗ |
g_cancellable_cancel (self->get_jobs_cancellable); |
964 |
|
✗ |
g_cancellable_cancel (self->check_clean_heads_cancellable); |
965 |
|
|
|
966 |
|
✗ |
g_clear_pointer (&self->printer_name, g_free); |
967 |
|
✗ |
g_clear_pointer (&self->printer_location, g_free); |
968 |
|
✗ |
g_clear_pointer (&self->printer_make_and_model, g_free); |
969 |
|
✗ |
g_clear_pointer (&self->printer_hostname, g_free); |
970 |
|
✗ |
g_clear_pointer (&self->inklevel, ink_level_data_free); |
971 |
|
✗ |
g_clear_object (&self->get_jobs_cancellable); |
972 |
|
✗ |
g_clear_object (&self->check_clean_heads_cancellable); |
973 |
|
✗ |
g_clear_object (&self->clean_command); |
974 |
|
|
|
975 |
|
✗ |
G_OBJECT_CLASS (pp_printer_entry_parent_class)->dispose (object); |
976 |
|
✗ |
} |
977 |
|
|
|
978 |
|
|
static void |
979 |
|
✗ |
pp_printer_entry_get_property (GObject *object, |
980 |
|
|
guint prop_id, |
981 |
|
|
GValue *value, |
982 |
|
|
GParamSpec *pspec) |
983 |
|
|
{ |
984 |
|
✗ |
PpPrinterEntry *self = PP_PRINTER_ENTRY (object); |
985 |
|
|
|
986 |
|
✗ |
switch (prop_id) |
987 |
|
|
{ |
988 |
|
✗ |
case PROP_DEFAULT: |
989 |
|
✗ |
g_value_set_boolean (value, self->is_default); |
990 |
|
✗ |
break; |
991 |
|
✗ |
case PROP_COMPACT: |
992 |
|
✗ |
g_value_set_boolean (value, self->compact); |
993 |
|
✗ |
break; |
994 |
|
✗ |
default: |
995 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
996 |
|
|
} |
997 |
|
✗ |
} |
998 |
|
|
|
999 |
|
|
static void |
1000 |
|
✗ |
pp_printer_entry_set_property (GObject *object, |
1001 |
|
|
guint prop_id, |
1002 |
|
|
const GValue *value, |
1003 |
|
|
GParamSpec *pspec) |
1004 |
|
|
{ |
1005 |
|
✗ |
PpPrinterEntry *self = PP_PRINTER_ENTRY (object); |
1006 |
|
|
|
1007 |
|
✗ |
switch (prop_id) |
1008 |
|
|
{ |
1009 |
|
✗ |
case PROP_DEFAULT: |
1010 |
|
✗ |
set_as_default_printer (self); |
1011 |
|
✗ |
break; |
1012 |
|
✗ |
case PROP_COMPACT: |
1013 |
|
✗ |
set_compact (self, g_value_get_boolean (value)); |
1014 |
|
✗ |
break; |
1015 |
|
✗ |
default: |
1016 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1017 |
|
|
} |
1018 |
|
✗ |
} |
1019 |
|
|
|
1020 |
|
|
static void |
1021 |
|
✗ |
pp_printer_entry_class_init (PpPrinterEntryClass *klass) |
1022 |
|
|
{ |
1023 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
1024 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1025 |
|
|
|
1026 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/printer-entry.ui"); |
1027 |
|
|
|
1028 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, header_box); |
1029 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_name_label); |
1030 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_status); |
1031 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_model_label); |
1032 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_model); |
1033 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_location_label); |
1034 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_location_address_label); |
1035 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_inklevel_label); |
1036 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, supply_frame); |
1037 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, supply_drawing_area); |
1038 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, show_jobs_dialog_button); |
1039 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, error_status); |
1040 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, PpPrinterEntry, printer_error); |
1041 |
|
|
|
1042 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, show_jobs_dialog); |
1043 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, restart_printer); |
1044 |
|
|
|
1045 |
|
✗ |
object_class->dispose = pp_printer_entry_dispose; |
1046 |
|
✗ |
object_class->get_property = pp_printer_entry_get_property; |
1047 |
|
✗ |
object_class->set_property = pp_printer_entry_set_property; |
1048 |
|
|
|
1049 |
|
✗ |
g_object_class_install_property (object_class, |
1050 |
|
|
PROP_DEFAULT, |
1051 |
|
|
g_param_spec_boolean ("default", |
1052 |
|
|
"default", |
1053 |
|
|
"default", |
1054 |
|
|
FALSE, |
1055 |
|
|
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY)); |
1056 |
|
|
|
1057 |
|
✗ |
g_object_class_install_property (object_class, |
1058 |
|
|
PROP_COMPACT, |
1059 |
|
|
g_param_spec_boolean ("compact", |
1060 |
|
|
"compact", |
1061 |
|
|
"compact", |
1062 |
|
|
FALSE, |
1063 |
|
|
G_PARAM_READWRITE)); |
1064 |
|
|
|
1065 |
|
✗ |
signals[IS_DEFAULT_PRINTER] = |
1066 |
|
✗ |
g_signal_new ("printer-changed", |
1067 |
|
|
G_TYPE_FROM_CLASS (klass), |
1068 |
|
|
G_SIGNAL_RUN_LAST, |
1069 |
|
|
0, |
1070 |
|
|
NULL, NULL, NULL, |
1071 |
|
|
G_TYPE_NONE, 0); |
1072 |
|
|
|
1073 |
|
✗ |
signals[PRINTER_DELETE] = |
1074 |
|
✗ |
g_signal_new ("printer-delete", |
1075 |
|
|
G_TYPE_FROM_CLASS (klass), |
1076 |
|
|
G_SIGNAL_RUN_LAST, |
1077 |
|
|
0, |
1078 |
|
|
NULL, NULL, NULL, |
1079 |
|
|
G_TYPE_NONE, 0); |
1080 |
|
|
|
1081 |
|
✗ |
signals[PRINTER_RENAMED] = |
1082 |
|
✗ |
g_signal_new ("printer-renamed", |
1083 |
|
|
G_TYPE_FROM_CLASS (klass), |
1084 |
|
|
G_SIGNAL_RUN_LAST, |
1085 |
|
|
0, |
1086 |
|
|
NULL, NULL, NULL, |
1087 |
|
|
G_TYPE_NONE, 1, |
1088 |
|
|
G_TYPE_STRING); |
1089 |
|
|
|
1090 |
|
✗ |
gtk_widget_class_install_action (widget_class, "printer.options", NULL, |
1091 |
|
|
(GtkWidgetActionActivateFunc) printer_options_cb); |
1092 |
|
✗ |
gtk_widget_class_install_action (widget_class, "printer.details", NULL, |
1093 |
|
|
(GtkWidgetActionActivateFunc) printer_details_cb); |
1094 |
|
✗ |
gtk_widget_class_install_property_action (widget_class, "printer.default", "default"); |
1095 |
|
✗ |
gtk_widget_class_install_action (widget_class, "printer.clean-heads", NULL, |
1096 |
|
|
(GtkWidgetActionActivateFunc) printer_clean_heads_cb); |
1097 |
|
✗ |
gtk_widget_class_install_action (widget_class, "printer.remove", NULL, |
1098 |
|
|
(GtkWidgetActionActivateFunc) printer_remove_cb); |
1099 |
|
✗ |
} |
1100 |
|
|
|