Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* Copyright (C) 2010 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 |
|
|
*/ |
18 |
|
|
|
19 |
|
|
#include <config.h> |
20 |
|
|
|
21 |
|
|
#include "shell/cc-object-storage.h" |
22 |
|
|
|
23 |
|
|
#include "cc-printers-panel.h" |
24 |
|
|
#include "cc-printers-resources.h" |
25 |
|
|
#include "pp-printer.h" |
26 |
|
|
|
27 |
|
|
#include <string.h> |
28 |
|
|
#include <glib/gi18n-lib.h> |
29 |
|
|
#include <glib/gstdio.h> |
30 |
|
|
#include <polkit/polkit.h> |
31 |
|
|
#include <gdesktop-enums.h> |
32 |
|
|
|
33 |
|
|
#include <cups/cups.h> |
34 |
|
|
#include <cups/ppd.h> |
35 |
|
|
|
36 |
|
|
#include <math.h> |
37 |
|
|
|
38 |
|
|
#include "pp-new-printer-dialog.h" |
39 |
|
|
#include "pp-utils.h" |
40 |
|
|
#include "pp-cups.h" |
41 |
|
|
#include "pp-printer-entry.h" |
42 |
|
|
#include "pp-job.h" |
43 |
|
|
#include "pp-new-printer.h" |
44 |
|
|
|
45 |
|
|
#include "cc-permission-infobar.h" |
46 |
|
|
#include "cc-util.h" |
47 |
|
|
|
48 |
|
|
#define JOB_DEFAULT_PRIORITY 50 |
49 |
|
|
#define RENEW_INTERVAL 500 |
50 |
|
|
#define SUBSCRIPTION_DURATION 600 |
51 |
|
|
|
52 |
|
|
#define CUPS_DBUS_NAME "org.cups.cupsd.Notifier" |
53 |
|
|
#define CUPS_DBUS_PATH "/org/cups/cupsd/Notifier" |
54 |
|
|
#define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier" |
55 |
|
|
|
56 |
|
|
#define CUPS_STATUS_CHECK_INTERVAL 5 |
57 |
|
|
|
58 |
|
|
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5) |
59 |
|
|
#define HAVE_CUPS_1_6 1 |
60 |
|
|
#endif |
61 |
|
|
|
62 |
|
|
#ifndef HAVE_CUPS_1_6 |
63 |
|
|
#define ippGetState(ipp) ipp->state |
64 |
|
|
#define ippGetStatusCode(ipp) ipp->request.status.status_code |
65 |
|
|
#define ippGetString(attr, element, language) attr->values[element].string.text |
66 |
|
|
#endif |
67 |
|
|
|
68 |
|
|
struct _CcPrintersPanel |
69 |
|
|
{ |
70 |
|
|
CcPanel parent_instance; |
71 |
|
|
|
72 |
|
|
GtkListBox *content; |
73 |
|
|
GtkStack *main_stack; |
74 |
|
|
GtkRevealer *notification; |
75 |
|
|
GtkLabel *notification_label; |
76 |
|
|
CcPermissionInfobar *permission_infobar; |
77 |
|
|
GtkWidget *printer_add_button; |
78 |
|
|
GtkWidget *printer_add_button_empty; |
79 |
|
|
GtkScrolledWindow *scrolled_window; |
80 |
|
|
GtkSearchBar *search_bar; |
81 |
|
|
GtkWidget *search_button; |
82 |
|
|
GtkEditable *search_entry; |
83 |
|
|
|
84 |
|
|
PpCups *cups; |
85 |
|
|
|
86 |
|
|
cups_dest_t *dests; |
87 |
|
|
int num_dests; |
88 |
|
|
|
89 |
|
|
GPermission *permission; |
90 |
|
|
gboolean is_authorized; |
91 |
|
|
|
92 |
|
|
GSettings *lockdown_settings; |
93 |
|
|
|
94 |
|
|
PpNewPrinterDialog *pp_new_printer_dialog; |
95 |
|
|
|
96 |
|
|
GDBusProxy *cups_proxy; |
97 |
|
|
GDBusConnection *cups_bus_connection; |
98 |
|
|
gint subscription_id; |
99 |
|
|
guint subscription_renewal_id; |
100 |
|
|
guint cups_status_check_id; |
101 |
|
|
guint dbus_subscription_id; |
102 |
|
|
guint remove_printer_timeout_id; |
103 |
|
|
|
104 |
|
|
PPDList *all_ppds_list; |
105 |
|
|
|
106 |
|
|
gchar *new_printer_name; |
107 |
|
|
|
108 |
|
|
gchar *renamed_printer_name; |
109 |
|
|
gchar *old_printer_name; |
110 |
|
|
gchar *deleted_printer_name; |
111 |
|
|
GList *deleted_printers; |
112 |
|
|
GObject *reference; |
113 |
|
|
|
114 |
|
|
GHashTable *printer_entries; |
115 |
|
|
gboolean entries_filled; |
116 |
|
|
GVariant *action; |
117 |
|
|
|
118 |
|
|
GtkSizeGroup *size_group; |
119 |
|
|
gboolean compact; |
120 |
|
|
}; |
121 |
|
|
|
122 |
|
✗ |
CC_PANEL_REGISTER (CcPrintersPanel, cc_printers_panel) |
123 |
|
|
|
124 |
|
|
typedef struct |
125 |
|
|
{ |
126 |
|
|
gchar *printer_name; |
127 |
|
|
GCancellable *cancellable; |
128 |
|
|
} SetPPDItem; |
129 |
|
|
|
130 |
|
|
enum { |
131 |
|
|
PROP_0, |
132 |
|
|
PROP_PARAMETERS, |
133 |
|
|
PROP_COMPACT, |
134 |
|
|
}; |
135 |
|
|
|
136 |
|
|
static void actualize_printers_list (CcPrintersPanel *self); |
137 |
|
|
static void update_sensitivity (gpointer user_data); |
138 |
|
|
static void detach_from_cups_notifier (gpointer data); |
139 |
|
|
static void free_dests (CcPrintersPanel *self); |
140 |
|
|
static void set_current_page (GObject *source_object, |
141 |
|
|
GAsyncResult *result, |
142 |
|
|
gpointer user_data); |
143 |
|
|
|
144 |
|
|
static void |
145 |
|
✗ |
execute_action (CcPrintersPanel *self, |
146 |
|
|
GVariant *action) |
147 |
|
|
{ |
148 |
|
|
PpPrinterEntry *printer_entry; |
149 |
|
|
const gchar *action_name; |
150 |
|
|
const gchar *printer_name; |
151 |
|
|
gint count; |
152 |
|
|
|
153 |
|
✗ |
count = g_variant_n_children (action); |
154 |
|
✗ |
if (count == 2) |
155 |
|
|
{ |
156 |
|
✗ |
g_autoptr(GVariant) action_variant = NULL; |
157 |
|
|
|
158 |
|
✗ |
g_variant_get_child (action, 0, "v", &action_variant); |
159 |
|
✗ |
action_name = g_variant_get_string (action_variant, NULL); |
160 |
|
|
|
161 |
|
|
/* authenticate-jobs printer-name */ |
162 |
|
✗ |
if (g_strcmp0 (action_name, "authenticate-jobs") == 0) |
163 |
|
|
{ |
164 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
165 |
|
|
|
166 |
|
✗ |
g_variant_get_child (action, 1, "v", &variant); |
167 |
|
✗ |
printer_name = g_variant_get_string (variant, NULL); |
168 |
|
|
|
169 |
|
✗ |
printer_entry = PP_PRINTER_ENTRY (g_hash_table_lookup (self->printer_entries, printer_name)); |
170 |
|
✗ |
if (printer_entry != NULL) |
171 |
|
✗ |
pp_printer_entry_authenticate_jobs (printer_entry); |
172 |
|
|
else |
173 |
|
✗ |
g_warning ("Could not find printer \"%s\"!", printer_name); |
174 |
|
|
} |
175 |
|
|
/* show-jobs printer-name */ |
176 |
|
✗ |
else if (g_strcmp0 (action_name, "show-jobs") == 0) |
177 |
|
|
{ |
178 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
179 |
|
|
|
180 |
|
✗ |
g_variant_get_child (action, 1, "v", &variant); |
181 |
|
✗ |
printer_name = g_variant_get_string (variant, NULL); |
182 |
|
|
|
183 |
|
✗ |
printer_entry = PP_PRINTER_ENTRY (g_hash_table_lookup (self->printer_entries, printer_name)); |
184 |
|
✗ |
if (printer_entry != NULL) |
185 |
|
✗ |
pp_printer_entry_show_jobs_dialog (printer_entry); |
186 |
|
|
else |
187 |
|
✗ |
g_warning ("Could not find printer \"%s\"!", printer_name); |
188 |
|
|
} |
189 |
|
|
} |
190 |
|
✗ |
} |
191 |
|
|
|
192 |
|
|
static void |
193 |
|
✗ |
cc_printers_panel_get_property (GObject *object, |
194 |
|
|
guint property_id, |
195 |
|
|
GValue *value, |
196 |
|
|
GParamSpec *pspec) |
197 |
|
|
{ |
198 |
|
✗ |
CcPrintersPanel *self = CC_PRINTERS_PANEL (object); |
199 |
|
|
|
200 |
|
✗ |
switch (property_id) |
201 |
|
|
{ |
202 |
|
✗ |
case PROP_COMPACT: |
203 |
|
✗ |
g_value_set_boolean (value, self->compact); |
204 |
|
✗ |
break; |
205 |
|
|
|
206 |
|
✗ |
default: |
207 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
208 |
|
|
} |
209 |
|
✗ |
} |
210 |
|
|
|
211 |
|
|
static void |
212 |
|
✗ |
cc_printers_panel_set_property (GObject *object, |
213 |
|
|
guint property_id, |
214 |
|
|
const GValue *value, |
215 |
|
|
GParamSpec *pspec) |
216 |
|
|
{ |
217 |
|
✗ |
CcPrintersPanel *self = CC_PRINTERS_PANEL (object); |
218 |
|
|
GVariant *parameters; |
219 |
|
|
|
220 |
|
✗ |
switch (property_id) |
221 |
|
|
{ |
222 |
|
✗ |
case PROP_PARAMETERS: |
223 |
|
✗ |
parameters = g_value_get_variant (value); |
224 |
|
✗ |
if (parameters != NULL && g_variant_n_children (parameters) > 0) |
225 |
|
|
{ |
226 |
|
✗ |
if (self->entries_filled) |
227 |
|
|
{ |
228 |
|
✗ |
execute_action (CC_PRINTERS_PANEL (object), parameters); |
229 |
|
|
} |
230 |
|
|
else |
231 |
|
|
{ |
232 |
|
✗ |
if (self->action != NULL) |
233 |
|
✗ |
g_variant_unref (self->action); |
234 |
|
✗ |
self->action = g_variant_ref (parameters); |
235 |
|
|
} |
236 |
|
|
} |
237 |
|
✗ |
break; |
238 |
|
|
|
239 |
|
✗ |
case PROP_COMPACT: |
240 |
|
✗ |
self->compact = g_value_get_boolean (value); |
241 |
|
✗ |
break; |
242 |
|
|
|
243 |
|
✗ |
default: |
244 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); |
245 |
|
|
} |
246 |
|
✗ |
} |
247 |
|
|
|
248 |
|
|
static void |
249 |
|
✗ |
cc_printers_panel_constructed (GObject *object) |
250 |
|
|
{ |
251 |
|
✗ |
CcPrintersPanel *self = CC_PRINTERS_PANEL (object); |
252 |
|
|
CcShell *shell; |
253 |
|
|
|
254 |
|
✗ |
G_OBJECT_CLASS (cc_printers_panel_parent_class)->constructed (object); |
255 |
|
|
|
256 |
|
✗ |
shell = cc_panel_get_shell (CC_PANEL (self)); |
257 |
|
|
|
258 |
|
✗ |
gtk_search_bar_connect_entry (self->search_bar, self->search_entry); |
259 |
|
✗ |
gtk_search_bar_set_key_capture_widget (self->search_bar, |
260 |
|
✗ |
GTK_WIDGET (shell)); |
261 |
|
✗ |
} |
262 |
|
|
|
263 |
|
|
static void |
264 |
|
✗ |
printer_removed_cb (GObject *source_object, |
265 |
|
|
GAsyncResult *result, |
266 |
|
|
gpointer user_data) |
267 |
|
|
{ |
268 |
|
✗ |
PpPrinter *printer = PP_PRINTER (source_object); |
269 |
|
✗ |
g_autoptr(GError) error = NULL; |
270 |
|
|
|
271 |
|
✗ |
pp_printer_delete_finish (printer, result, &error); |
272 |
|
|
|
273 |
|
✗ |
if (user_data != NULL) |
274 |
|
|
{ |
275 |
|
✗ |
g_autoptr(GObject) reference = G_OBJECT (user_data); |
276 |
|
|
|
277 |
|
✗ |
if (g_object_get_data (reference, "self") != NULL) |
278 |
|
|
{ |
279 |
|
✗ |
CcPrintersPanel *self = CC_PRINTERS_PANEL (g_object_get_data (reference, "self")); |
280 |
|
|
GList *iter; |
281 |
|
|
|
282 |
|
✗ |
for (iter = self->deleted_printers; iter != NULL; iter = iter->next) |
283 |
|
|
{ |
284 |
|
✗ |
if (g_strcmp0 (iter->data, pp_printer_get_name (printer)) == 0) |
285 |
|
|
{ |
286 |
|
✗ |
g_free (iter->data); |
287 |
|
✗ |
self->deleted_printers = g_list_delete_link (self->deleted_printers, iter); |
288 |
|
✗ |
break; |
289 |
|
|
} |
290 |
|
|
} |
291 |
|
|
} |
292 |
|
|
} |
293 |
|
|
|
294 |
|
✗ |
if (error != NULL) |
295 |
|
✗ |
g_warning ("Printer could not be deleted: %s", error->message); |
296 |
|
✗ |
} |
297 |
|
|
|
298 |
|
|
static void |
299 |
|
✗ |
cc_printers_panel_dispose (GObject *object) |
300 |
|
|
{ |
301 |
|
✗ |
CcPrintersPanel *self = CC_PRINTERS_PANEL (object); |
302 |
|
|
|
303 |
|
✗ |
detach_from_cups_notifier (CC_PRINTERS_PANEL (object)); |
304 |
|
|
|
305 |
|
✗ |
if (self->deleted_printer_name != NULL) |
306 |
|
|
{ |
307 |
|
✗ |
g_autoptr(PpPrinter) printer = pp_printer_new (self->deleted_printer_name); |
308 |
|
✗ |
pp_printer_delete_sync (printer, NULL, NULL); |
309 |
|
|
} |
310 |
|
|
|
311 |
|
✗ |
g_clear_object (&self->cups); |
312 |
|
✗ |
g_clear_pointer (&self->new_printer_name, g_free); |
313 |
|
✗ |
g_clear_pointer (&self->renamed_printer_name, g_free); |
314 |
|
✗ |
g_clear_pointer (&self->old_printer_name, g_free); |
315 |
|
✗ |
g_clear_object (&self->lockdown_settings); |
316 |
|
✗ |
g_clear_object (&self->permission); |
317 |
|
✗ |
g_clear_handle_id (&self->cups_status_check_id, g_source_remove); |
318 |
|
✗ |
g_clear_handle_id (&self->remove_printer_timeout_id, g_source_remove); |
319 |
|
✗ |
g_clear_pointer (&self->deleted_printer_name, g_free); |
320 |
|
✗ |
g_clear_pointer (&self->action, g_variant_unref); |
321 |
|
✗ |
g_clear_pointer (&self->printer_entries, g_hash_table_destroy); |
322 |
|
✗ |
g_clear_pointer (&self->all_ppds_list, ppd_list_free); |
323 |
|
✗ |
free_dests (self); |
324 |
|
✗ |
g_list_free_full (self->deleted_printers, g_free); |
325 |
|
✗ |
self->deleted_printers = NULL; |
326 |
|
✗ |
if (self->reference != NULL) |
327 |
|
✗ |
g_object_set_data (self->reference, "self", NULL); |
328 |
|
✗ |
g_clear_object (&self->reference); |
329 |
|
|
|
330 |
|
✗ |
G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object); |
331 |
|
✗ |
} |
332 |
|
|
|
333 |
|
|
static const char * |
334 |
|
✗ |
cc_printers_panel_get_help_uri (CcPanel *panel) |
335 |
|
|
{ |
336 |
|
✗ |
return "help:gnome-help/printing"; |
337 |
|
|
} |
338 |
|
|
|
339 |
|
|
static void |
340 |
|
✗ |
on_get_job_attributes_cb (GObject *source_object, |
341 |
|
|
GAsyncResult *res, |
342 |
|
|
gpointer user_data) |
343 |
|
|
{ |
344 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
345 |
|
|
const gchar *job_originating_user_name; |
346 |
|
|
const gchar *job_printer_uri; |
347 |
|
✗ |
g_autoptr(GVariant) attributes = NULL; |
348 |
|
✗ |
g_autoptr(GError) error = NULL; |
349 |
|
|
|
350 |
|
✗ |
attributes = pp_job_get_attributes_finish (PP_JOB (source_object), res, &error); |
351 |
|
|
|
352 |
|
✗ |
if (attributes != NULL) |
353 |
|
|
{ |
354 |
|
✗ |
g_autoptr(GVariant) username = NULL; |
355 |
|
|
|
356 |
|
✗ |
if ((username = g_variant_lookup_value (attributes, "job-originating-user-name", G_VARIANT_TYPE ("as"))) != NULL) |
357 |
|
|
{ |
358 |
|
✗ |
g_autoptr(GVariant) printer_uri = NULL; |
359 |
|
|
|
360 |
|
✗ |
if ((printer_uri = g_variant_lookup_value (attributes, "job-printer-uri", G_VARIANT_TYPE ("as"))) != NULL) |
361 |
|
|
{ |
362 |
|
✗ |
job_originating_user_name = g_variant_get_string (g_variant_get_child_value (username, 0), NULL); |
363 |
|
✗ |
job_printer_uri = g_variant_get_string (g_variant_get_child_value (printer_uri, 0), NULL); |
364 |
|
|
|
365 |
|
✗ |
if (job_originating_user_name != NULL && job_printer_uri != NULL && |
366 |
|
✗ |
g_strcmp0 (job_originating_user_name, cupsUser ()) == 0 && |
367 |
|
✗ |
g_strrstr (job_printer_uri, "/") != 0 && |
368 |
|
✗ |
self->dests != NULL) |
369 |
|
|
{ |
370 |
|
|
PpPrinterEntry *printer_entry; |
371 |
|
|
gchar *printer_name; |
372 |
|
|
|
373 |
|
✗ |
printer_name = g_strrstr (job_printer_uri, "/") + 1; |
374 |
|
✗ |
printer_entry = PP_PRINTER_ENTRY (g_hash_table_lookup (self->printer_entries, printer_name)); |
375 |
|
|
|
376 |
|
✗ |
pp_printer_entry_update_jobs_count (printer_entry); |
377 |
|
|
} |
378 |
|
|
} |
379 |
|
|
} |
380 |
|
|
} |
381 |
|
✗ |
} |
382 |
|
|
|
383 |
|
|
static void |
384 |
|
✗ |
on_cups_notification (GDBusConnection *connection, |
385 |
|
|
const char *sender_name, |
386 |
|
|
const char *object_path, |
387 |
|
|
const char *interface_name, |
388 |
|
|
const char *signal_name, |
389 |
|
|
GVariant *parameters, |
390 |
|
|
gpointer user_data) |
391 |
|
|
{ |
392 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
393 |
|
|
gboolean printer_is_accepting_jobs; |
394 |
|
✗ |
gchar *printer_name = NULL; |
395 |
|
✗ |
gchar *text = NULL; |
396 |
|
✗ |
gchar *printer_uri = NULL; |
397 |
|
✗ |
gchar *printer_state_reasons = NULL; |
398 |
|
✗ |
gchar *job_state_reasons = NULL; |
399 |
|
✗ |
gchar *job_name = NULL; |
400 |
|
|
guint job_id; |
401 |
|
|
gint printer_state; |
402 |
|
|
gint job_state; |
403 |
|
|
gint job_impressions_completed; |
404 |
|
|
static gchar *requested_attrs[] = { |
405 |
|
|
"job-printer-uri", |
406 |
|
|
"job-originating-user-name", |
407 |
|
|
NULL }; |
408 |
|
|
|
409 |
|
✗ |
if (g_strcmp0 (signal_name, "PrinterAdded") != 0 && |
410 |
|
✗ |
g_strcmp0 (signal_name, "PrinterDeleted") != 0 && |
411 |
|
✗ |
g_strcmp0 (signal_name, "PrinterStateChanged") != 0 && |
412 |
|
✗ |
g_strcmp0 (signal_name, "PrinterStopped") != 0 && |
413 |
|
✗ |
g_strcmp0 (signal_name, "JobCreated") != 0 && |
414 |
|
✗ |
g_strcmp0 (signal_name, "JobCompleted") != 0) |
415 |
|
✗ |
return; |
416 |
|
|
|
417 |
|
✗ |
if (g_variant_n_children (parameters) == 1) |
418 |
|
✗ |
g_variant_get (parameters, "(&s)", &text); |
419 |
|
✗ |
else if (g_variant_n_children (parameters) == 6) |
420 |
|
|
{ |
421 |
|
✗ |
g_variant_get (parameters, "(&s&s&su&sb)", |
422 |
|
|
&text, |
423 |
|
|
&printer_uri, |
424 |
|
|
&printer_name, |
425 |
|
|
&printer_state, |
426 |
|
|
&printer_state_reasons, |
427 |
|
|
&printer_is_accepting_jobs); |
428 |
|
|
} |
429 |
|
✗ |
else if (g_variant_n_children (parameters) == 11) |
430 |
|
|
{ |
431 |
|
✗ |
g_variant_get (parameters, "(&s&s&su&sbuu&s&su)", |
432 |
|
|
&text, |
433 |
|
|
&printer_uri, |
434 |
|
|
&printer_name, |
435 |
|
|
&printer_state, |
436 |
|
|
&printer_state_reasons, |
437 |
|
|
&printer_is_accepting_jobs, |
438 |
|
|
&job_id, |
439 |
|
|
&job_state, |
440 |
|
|
&job_state_reasons, |
441 |
|
|
&job_name, |
442 |
|
|
&job_impressions_completed); |
443 |
|
|
} |
444 |
|
|
|
445 |
|
✗ |
if (g_strcmp0 (signal_name, "PrinterAdded") == 0 || |
446 |
|
✗ |
g_strcmp0 (signal_name, "PrinterDeleted") == 0 || |
447 |
|
✗ |
g_strcmp0 (signal_name, "PrinterStateChanged") == 0 || |
448 |
|
✗ |
g_strcmp0 (signal_name, "PrinterStopped") == 0) |
449 |
|
✗ |
actualize_printers_list (self); |
450 |
|
✗ |
else if (g_strcmp0 (signal_name, "JobCreated") == 0 || |
451 |
|
✗ |
g_strcmp0 (signal_name, "JobCompleted") == 0) |
452 |
|
|
{ |
453 |
|
✗ |
g_autoptr(PpJob) job = NULL; |
454 |
|
|
|
455 |
|
✗ |
job = pp_job_new (job_id, NULL, 0, JOB_DEFAULT_PRIORITY, NULL); |
456 |
|
✗ |
pp_job_get_attributes_async (job, |
457 |
|
|
requested_attrs, |
458 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
459 |
|
|
on_get_job_attributes_cb, |
460 |
|
|
self); |
461 |
|
|
} |
462 |
|
|
} |
463 |
|
|
|
464 |
|
|
static gchar *subscription_events[] = { |
465 |
|
|
"printer-added", |
466 |
|
|
"printer-deleted", |
467 |
|
|
"printer-stopped", |
468 |
|
|
"printer-state-changed", |
469 |
|
|
"job-created", |
470 |
|
|
"job-completed", |
471 |
|
|
NULL}; |
472 |
|
|
|
473 |
|
|
static void |
474 |
|
✗ |
renew_subscription_cb (GObject *source_object, |
475 |
|
|
GAsyncResult *result, |
476 |
|
|
gpointer user_data) |
477 |
|
|
{ |
478 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
479 |
|
|
gint subscription_id; |
480 |
|
|
|
481 |
|
✗ |
subscription_id = pp_cups_renew_subscription_finish (PP_CUPS (source_object), result); |
482 |
|
|
|
483 |
|
✗ |
if (subscription_id > 0) |
484 |
|
✗ |
self->subscription_id = subscription_id; |
485 |
|
✗ |
} |
486 |
|
|
|
487 |
|
|
static gboolean |
488 |
|
✗ |
renew_subscription (gpointer data) |
489 |
|
|
{ |
490 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) data; |
491 |
|
|
|
492 |
|
✗ |
pp_cups_renew_subscription_async (self->cups, |
493 |
|
|
self->subscription_id, |
494 |
|
|
subscription_events, |
495 |
|
|
SUBSCRIPTION_DURATION, |
496 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
497 |
|
|
renew_subscription_cb, |
498 |
|
|
data); |
499 |
|
|
|
500 |
|
✗ |
return G_SOURCE_CONTINUE; |
501 |
|
|
} |
502 |
|
|
|
503 |
|
|
static void |
504 |
|
✗ |
attach_to_cups_notifier_cb (GObject *source_object, |
505 |
|
|
GAsyncResult *result, |
506 |
|
|
gpointer user_data) |
507 |
|
|
{ |
508 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
509 |
|
✗ |
g_autoptr(GError) error = NULL; |
510 |
|
|
gint subscription_id; |
511 |
|
|
|
512 |
|
✗ |
subscription_id = pp_cups_renew_subscription_finish (PP_CUPS (source_object), result); |
513 |
|
|
|
514 |
|
✗ |
if (subscription_id > 0) |
515 |
|
|
{ |
516 |
|
✗ |
self->subscription_id = subscription_id; |
517 |
|
|
|
518 |
|
✗ |
self->subscription_renewal_id = |
519 |
|
✗ |
g_timeout_add_seconds (RENEW_INTERVAL, renew_subscription, self); |
520 |
|
|
|
521 |
|
✗ |
self->cups_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, |
522 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
523 |
|
|
CUPS_DBUS_NAME, |
524 |
|
|
CUPS_DBUS_PATH, |
525 |
|
|
CUPS_DBUS_INTERFACE, |
526 |
|
|
NULL, |
527 |
|
|
&error); |
528 |
|
|
|
529 |
|
✗ |
if (!self->cups_proxy) |
530 |
|
|
{ |
531 |
|
✗ |
g_warning ("%s", error->message); |
532 |
|
✗ |
return; |
533 |
|
|
} |
534 |
|
|
|
535 |
|
✗ |
self->cups_bus_connection = g_dbus_proxy_get_connection (self->cups_proxy); |
536 |
|
|
|
537 |
|
✗ |
self->dbus_subscription_id = |
538 |
|
✗ |
g_dbus_connection_signal_subscribe (self->cups_bus_connection, |
539 |
|
|
NULL, |
540 |
|
|
CUPS_DBUS_INTERFACE, |
541 |
|
|
NULL, |
542 |
|
|
CUPS_DBUS_PATH, |
543 |
|
|
NULL, |
544 |
|
|
0, |
545 |
|
|
on_cups_notification, |
546 |
|
|
self, |
547 |
|
|
NULL); |
548 |
|
|
} |
549 |
|
|
} |
550 |
|
|
|
551 |
|
|
static void |
552 |
|
✗ |
attach_to_cups_notifier (gpointer data) |
553 |
|
|
{ |
554 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) data; |
555 |
|
|
|
556 |
|
✗ |
pp_cups_renew_subscription_async (self->cups, |
557 |
|
|
self->subscription_id, |
558 |
|
|
subscription_events, |
559 |
|
|
SUBSCRIPTION_DURATION, |
560 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
561 |
|
|
attach_to_cups_notifier_cb, |
562 |
|
|
data); |
563 |
|
✗ |
} |
564 |
|
|
|
565 |
|
|
static void |
566 |
|
✗ |
subscription_cancel_cb (GObject *source_object, |
567 |
|
|
GAsyncResult *result, |
568 |
|
|
gpointer user_data) |
569 |
|
|
{ |
570 |
|
✗ |
pp_cups_cancel_subscription_finish (PP_CUPS (source_object), result); |
571 |
|
✗ |
} |
572 |
|
|
|
573 |
|
|
static void |
574 |
|
✗ |
detach_from_cups_notifier (gpointer data) |
575 |
|
|
{ |
576 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) data; |
577 |
|
|
|
578 |
|
✗ |
if (self->dbus_subscription_id != 0) { |
579 |
|
✗ |
g_dbus_connection_signal_unsubscribe (self->cups_bus_connection, |
580 |
|
|
self->dbus_subscription_id); |
581 |
|
✗ |
self->dbus_subscription_id = 0; |
582 |
|
|
} |
583 |
|
|
|
584 |
|
✗ |
pp_cups_cancel_subscription_async (self->cups, |
585 |
|
|
self->subscription_id, |
586 |
|
|
subscription_cancel_cb, |
587 |
|
|
NULL); |
588 |
|
|
|
589 |
|
✗ |
self->subscription_id = 0; |
590 |
|
|
|
591 |
|
✗ |
g_clear_handle_id (&self->subscription_renewal_id, g_source_remove); |
592 |
|
|
|
593 |
|
✗ |
g_clear_object (&self->cups_proxy); |
594 |
|
✗ |
} |
595 |
|
|
|
596 |
|
|
static void |
597 |
|
✗ |
free_dests (CcPrintersPanel *self) |
598 |
|
|
{ |
599 |
|
✗ |
if (self->num_dests > 0) |
600 |
|
|
{ |
601 |
|
✗ |
cupsFreeDests (self->num_dests, self->dests); |
602 |
|
|
} |
603 |
|
✗ |
self->dests = NULL; |
604 |
|
✗ |
self->num_dests = 0; |
605 |
|
✗ |
} |
606 |
|
|
|
607 |
|
|
static void |
608 |
|
✗ |
on_printer_deletion_undone (CcPrintersPanel *self) |
609 |
|
|
{ |
610 |
|
✗ |
gtk_revealer_set_reveal_child (self->notification, FALSE); |
611 |
|
|
|
612 |
|
✗ |
g_clear_pointer (&self->deleted_printer_name, g_free); |
613 |
|
|
|
614 |
|
✗ |
gtk_list_box_invalidate_filter (self->content); |
615 |
|
|
|
616 |
|
✗ |
g_clear_handle_id (&self->remove_printer_timeout_id, g_source_remove); |
617 |
|
|
|
618 |
|
✗ |
if (self->num_dests > 0) |
619 |
|
✗ |
gtk_stack_set_visible_child_name (self->main_stack, "printers-list"); |
620 |
|
✗ |
} |
621 |
|
|
|
622 |
|
|
static void |
623 |
|
✗ |
on_notification_dismissed (CcPrintersPanel *self) |
624 |
|
|
{ |
625 |
|
✗ |
g_clear_handle_id (&self->remove_printer_timeout_id, g_source_remove); |
626 |
|
|
|
627 |
|
✗ |
if (self->deleted_printer_name != NULL) |
628 |
|
|
{ |
629 |
|
✗ |
g_autoptr(PpPrinter) printer = NULL; |
630 |
|
|
|
631 |
|
✗ |
printer = pp_printer_new (self->deleted_printer_name); |
632 |
|
|
/* The reference tells to the callback whether |
633 |
|
|
printers panel was already destroyed so |
634 |
|
|
it knows whether it can access the list |
635 |
|
|
of deleted printers in it (see below). |
636 |
|
|
*/ |
637 |
|
✗ |
pp_printer_delete_async (printer, |
638 |
|
|
NULL, |
639 |
|
|
printer_removed_cb, |
640 |
|
✗ |
g_object_ref (self->reference)); |
641 |
|
|
|
642 |
|
|
/* List of printers which were recently deleted but are still available |
643 |
|
|
in CUPS due to async nature of the method (e.g. quick deletion |
644 |
|
|
of several printers). |
645 |
|
|
*/ |
646 |
|
✗ |
self->deleted_printers = g_list_prepend (self->deleted_printers, self->deleted_printer_name); |
647 |
|
✗ |
self->deleted_printer_name = NULL; |
648 |
|
|
} |
649 |
|
|
|
650 |
|
✗ |
gtk_revealer_set_reveal_child (self->notification, FALSE); |
651 |
|
✗ |
} |
652 |
|
|
|
653 |
|
|
static gboolean |
654 |
|
✗ |
on_remove_printer_timeout (CcPrintersPanel *self) |
655 |
|
|
{ |
656 |
|
✗ |
self->remove_printer_timeout_id = 0; |
657 |
|
|
|
658 |
|
✗ |
on_notification_dismissed (self); |
659 |
|
|
|
660 |
|
✗ |
return G_SOURCE_REMOVE; |
661 |
|
|
} |
662 |
|
|
|
663 |
|
|
static void |
664 |
|
✗ |
on_printer_deleted (CcPrintersPanel *self, |
665 |
|
|
PpPrinterEntry *printer_entry) |
666 |
|
|
{ |
667 |
|
✗ |
g_autofree gchar *notification_message = NULL; |
668 |
|
|
|
669 |
|
✗ |
on_notification_dismissed (self); |
670 |
|
|
|
671 |
|
|
/* Translators: %s is the printer name */ |
672 |
|
✗ |
notification_message = g_strdup_printf (_("Printer “%s” has been deleted"), |
673 |
|
|
pp_printer_entry_get_name (printer_entry)); |
674 |
|
✗ |
gtk_label_set_label (self->notification_label, notification_message); |
675 |
|
|
|
676 |
|
✗ |
self->deleted_printer_name = g_strdup (pp_printer_entry_get_name (printer_entry)); |
677 |
|
|
|
678 |
|
✗ |
gtk_list_box_invalidate_filter (self->content); |
679 |
|
|
|
680 |
|
✗ |
gtk_revealer_set_reveal_child (self->notification, TRUE); |
681 |
|
|
|
682 |
|
✗ |
self->remove_printer_timeout_id = g_timeout_add_seconds (10, G_SOURCE_FUNC (on_remove_printer_timeout), self); |
683 |
|
|
|
684 |
|
✗ |
if (self->num_dests == 1 + g_list_length (self->deleted_printers)) |
685 |
|
✗ |
pp_cups_connection_test_async (self->cups, NULL, set_current_page, self); |
686 |
|
✗ |
} |
687 |
|
|
|
688 |
|
|
static void |
689 |
|
✗ |
on_printer_renamed (CcPrintersPanel *self, |
690 |
|
|
gchar *new_name, |
691 |
|
|
PpPrinterEntry *printer_entry) |
692 |
|
|
{ |
693 |
|
✗ |
self->old_printer_name = g_strdup (pp_printer_entry_get_name (printer_entry)); |
694 |
|
✗ |
self->renamed_printer_name = g_strdup (new_name); |
695 |
|
✗ |
} |
696 |
|
|
|
697 |
|
|
static void |
698 |
|
✗ |
on_printer_changed (CcPrintersPanel *self) |
699 |
|
|
{ |
700 |
|
✗ |
actualize_printers_list (self); |
701 |
|
✗ |
} |
702 |
|
|
|
703 |
|
|
static void |
704 |
|
✗ |
add_printer_entry (CcPrintersPanel *self, |
705 |
|
|
cups_dest_t printer) |
706 |
|
|
{ |
707 |
|
|
PpPrinterEntry *printer_entry; |
708 |
|
|
GSList *widgets, *l; |
709 |
|
|
|
710 |
|
✗ |
printer_entry = pp_printer_entry_new (printer, self->is_authorized); |
711 |
|
|
|
712 |
|
✗ |
widgets = pp_printer_entry_get_size_group_widgets (printer_entry); |
713 |
|
✗ |
for (l = widgets; l != NULL; l = l->next) |
714 |
|
✗ |
gtk_size_group_add_widget (self->size_group, GTK_WIDGET (l->data)); |
715 |
|
✗ |
g_slist_free (widgets); |
716 |
|
|
|
717 |
|
✗ |
g_signal_connect_object (printer_entry, |
718 |
|
|
"printer-changed", |
719 |
|
|
G_CALLBACK (on_printer_changed), |
720 |
|
|
self, |
721 |
|
|
G_CONNECT_SWAPPED); |
722 |
|
✗ |
g_signal_connect_object (printer_entry, |
723 |
|
|
"printer-delete", |
724 |
|
|
G_CALLBACK (on_printer_deleted), |
725 |
|
|
self, |
726 |
|
|
G_CONNECT_SWAPPED); |
727 |
|
✗ |
g_signal_connect_object (printer_entry, |
728 |
|
|
"printer-renamed", |
729 |
|
|
G_CALLBACK (on_printer_renamed), |
730 |
|
|
self, |
731 |
|
|
G_CONNECT_SWAPPED); |
732 |
|
|
|
733 |
|
✗ |
g_object_bind_property (self, "compact", |
734 |
|
|
printer_entry, "compact", |
735 |
|
|
G_BINDING_SYNC_CREATE); |
736 |
|
|
|
737 |
|
✗ |
gtk_list_box_insert (self->content, GTK_WIDGET (printer_entry), -1); |
738 |
|
|
|
739 |
|
✗ |
g_hash_table_insert (self->printer_entries, g_strdup (printer.name), printer_entry); |
740 |
|
✗ |
} |
741 |
|
|
|
742 |
|
|
static void |
743 |
|
✗ |
set_current_page (GObject *source_object, |
744 |
|
|
GAsyncResult *result, |
745 |
|
|
gpointer user_data) |
746 |
|
|
{ |
747 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel *) user_data; |
748 |
|
|
gboolean success; |
749 |
|
|
|
750 |
|
✗ |
success = pp_cups_connection_test_finish (PP_CUPS (source_object), result, NULL); |
751 |
|
|
|
752 |
|
✗ |
if (success) |
753 |
|
✗ |
gtk_stack_set_visible_child_name (self->main_stack, "empty-state"); |
754 |
|
|
else |
755 |
|
✗ |
gtk_stack_set_visible_child_name (self->main_stack, "no-cups-page"); |
756 |
|
|
|
757 |
|
✗ |
update_sensitivity (user_data); |
758 |
|
✗ |
} |
759 |
|
|
|
760 |
|
|
static gboolean |
761 |
|
✗ |
remove_nonexisting_entry (CcPrintersPanel *self, |
762 |
|
|
PpPrinterEntry *entry) |
763 |
|
|
{ |
764 |
|
✗ |
gboolean exists = FALSE; |
765 |
|
|
gint i; |
766 |
|
|
|
767 |
|
✗ |
for (i = 0; i < self->num_dests; i++) |
768 |
|
|
{ |
769 |
|
✗ |
if (g_strcmp0 (self->dests[i].name, pp_printer_entry_get_name (entry)) == 0) |
770 |
|
|
{ |
771 |
|
✗ |
exists = TRUE; |
772 |
|
✗ |
break; |
773 |
|
|
} |
774 |
|
|
} |
775 |
|
|
|
776 |
|
✗ |
if (!exists) |
777 |
|
✗ |
g_hash_table_remove (self->printer_entries, pp_printer_entry_get_name (entry)); |
778 |
|
|
|
779 |
|
✗ |
return !exists; |
780 |
|
|
} |
781 |
|
|
|
782 |
|
|
static void |
783 |
|
✗ |
actualize_printers_list_cb (GObject *source_object, |
784 |
|
|
GAsyncResult *result, |
785 |
|
|
gpointer user_data) |
786 |
|
|
{ |
787 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
788 |
|
|
PpCupsDests *cups_dests; |
789 |
|
|
GtkWidget *child; |
790 |
|
✗ |
gboolean new_printer_available = FALSE; |
791 |
|
✗ |
g_autoptr(GError) error = NULL; |
792 |
|
|
gpointer item; |
793 |
|
|
int i; |
794 |
|
|
|
795 |
|
✗ |
cups_dests = pp_cups_get_dests_finish (PP_CUPS (source_object), result, &error); |
796 |
|
|
|
797 |
|
✗ |
if (cups_dests == NULL && error != NULL) |
798 |
|
|
{ |
799 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
800 |
|
|
{ |
801 |
|
✗ |
g_warning ("Could not get dests: %s", error->message); |
802 |
|
|
} |
803 |
|
|
|
804 |
|
✗ |
return; |
805 |
|
|
} |
806 |
|
|
|
807 |
|
✗ |
free_dests (self); |
808 |
|
✗ |
self->dests = cups_dests->dests; |
809 |
|
✗ |
self->num_dests = cups_dests->num_of_dests; |
810 |
|
✗ |
g_free (cups_dests); |
811 |
|
|
|
812 |
|
✗ |
if ((self->num_dests == 0 && self->new_printer_name == NULL) || |
813 |
|
✗ |
(self->num_dests == 1 + g_list_length (self->deleted_printers) && |
814 |
|
✗ |
self->deleted_printer_name != NULL)) |
815 |
|
✗ |
pp_cups_connection_test_async (PP_CUPS (source_object), NULL, set_current_page, self); |
816 |
|
|
else |
817 |
|
✗ |
gtk_stack_set_visible_child_name (self->main_stack, "printers-list"); |
818 |
|
|
|
819 |
|
✗ |
child = gtk_widget_get_first_child (GTK_WIDGET (self->content)); |
820 |
|
✗ |
while (child) |
821 |
|
|
{ |
822 |
|
✗ |
GtkWidget *next = gtk_widget_get_next_sibling (child); |
823 |
|
|
|
824 |
|
✗ |
if (remove_nonexisting_entry (self, PP_PRINTER_ENTRY (child))) |
825 |
|
✗ |
gtk_list_box_remove (self->content, child); |
826 |
|
|
|
827 |
|
✗ |
child = next; |
828 |
|
|
} |
829 |
|
|
|
830 |
|
✗ |
for (i = 0; i < self->num_dests; i++) |
831 |
|
|
{ |
832 |
|
✗ |
new_printer_available = g_strcmp0 (self->dests[i].name, self->renamed_printer_name) == 0; |
833 |
|
✗ |
if (new_printer_available) |
834 |
|
✗ |
break; |
835 |
|
|
} |
836 |
|
|
|
837 |
|
✗ |
for (i = 0; i < self->num_dests; i++) |
838 |
|
|
{ |
839 |
|
✗ |
if (new_printer_available && g_strcmp0 (self->dests[i].name, self->old_printer_name) == 0) |
840 |
|
✗ |
continue; |
841 |
|
|
|
842 |
|
✗ |
item = g_hash_table_lookup (self->printer_entries, self->dests[i].name); |
843 |
|
✗ |
if (item != NULL) |
844 |
|
✗ |
pp_printer_entry_update (PP_PRINTER_ENTRY (item), self->dests[i], self->is_authorized); |
845 |
|
|
else |
846 |
|
✗ |
add_printer_entry (self, self->dests[i]); |
847 |
|
|
} |
848 |
|
|
|
849 |
|
✗ |
if (!self->entries_filled) |
850 |
|
|
{ |
851 |
|
✗ |
if (self->action != NULL) |
852 |
|
|
{ |
853 |
|
✗ |
execute_action (self, self->action); |
854 |
|
✗ |
g_variant_unref (self->action); |
855 |
|
✗ |
self->action = NULL; |
856 |
|
|
} |
857 |
|
|
|
858 |
|
✗ |
self->entries_filled = TRUE; |
859 |
|
|
} |
860 |
|
|
|
861 |
|
✗ |
update_sensitivity (user_data); |
862 |
|
|
|
863 |
|
✗ |
if (self->new_printer_name != NULL) |
864 |
|
|
{ |
865 |
|
|
GtkAllocation allocation; |
866 |
|
|
GtkAdjustment *adjustment; |
867 |
|
|
GtkWidget *printer_entry; |
868 |
|
|
|
869 |
|
|
/* Scroll the view to show the newly added printer-entry. */ |
870 |
|
✗ |
adjustment = gtk_scrolled_window_get_vadjustment (self->scrolled_window); |
871 |
|
|
|
872 |
|
✗ |
printer_entry = GTK_WIDGET (g_hash_table_lookup (self->printer_entries, |
873 |
|
|
self->new_printer_name)); |
874 |
|
✗ |
if (printer_entry != NULL) |
875 |
|
|
{ |
876 |
|
✗ |
gtk_widget_get_allocation (printer_entry, &allocation); |
877 |
|
✗ |
g_clear_pointer (&self->new_printer_name, g_free); |
878 |
|
|
|
879 |
|
✗ |
gtk_adjustment_set_value (adjustment, |
880 |
|
✗ |
allocation.y - gtk_widget_get_margin_top (printer_entry)); |
881 |
|
|
} |
882 |
|
|
} |
883 |
|
|
} |
884 |
|
|
|
885 |
|
|
static void |
886 |
|
✗ |
actualize_printers_list (CcPrintersPanel *self) |
887 |
|
|
{ |
888 |
|
✗ |
pp_cups_get_dests_async (self->cups, |
889 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
890 |
|
|
actualize_printers_list_cb, |
891 |
|
|
self); |
892 |
|
✗ |
} |
893 |
|
|
|
894 |
|
|
static void |
895 |
|
✗ |
printer_add_async_cb (GObject *source_object, |
896 |
|
|
GAsyncResult *res, |
897 |
|
|
gpointer user_data) |
898 |
|
|
{ |
899 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
900 |
|
|
gboolean success; |
901 |
|
✗ |
g_autoptr(GError) error = NULL; |
902 |
|
|
|
903 |
|
✗ |
success = pp_new_printer_add_finish (PP_NEW_PRINTER (source_object), res, &error); |
904 |
|
|
|
905 |
|
✗ |
if (!success) |
906 |
|
|
{ |
907 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
908 |
|
|
{ |
909 |
|
✗ |
g_warning ("%s", error->message); |
910 |
|
|
|
911 |
|
|
GtkWidget *message_dialog; |
912 |
|
|
|
913 |
|
✗ |
message_dialog = gtk_message_dialog_new (NULL, |
914 |
|
|
0, |
915 |
|
|
GTK_MESSAGE_ERROR, |
916 |
|
|
GTK_BUTTONS_CLOSE, |
917 |
|
|
/* Translators: Addition of the new printer failed. */ |
918 |
|
✗ |
_("Failed to add new printer.")); |
919 |
|
✗ |
g_signal_connect (message_dialog, |
920 |
|
|
"response", |
921 |
|
|
G_CALLBACK (gtk_window_destroy), |
922 |
|
|
NULL); |
923 |
|
✗ |
gtk_window_present (GTK_WINDOW (message_dialog)); |
924 |
|
|
} |
925 |
|
|
} |
926 |
|
|
|
927 |
|
✗ |
actualize_printers_list (self); |
928 |
|
✗ |
} |
929 |
|
|
|
930 |
|
|
static void |
931 |
|
✗ |
new_printer_dialog_response_cb (GtkWindow *_dialog, |
932 |
|
|
gint response_id, |
933 |
|
|
gpointer user_data) |
934 |
|
|
{ |
935 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
936 |
|
✗ |
PpNewPrinterDialog *pp_new_printer_dialog = PP_NEW_PRINTER_DIALOG (_dialog); |
937 |
|
✗ |
g_autoptr(PpNewPrinter) new_printer = NULL; |
938 |
|
|
|
939 |
|
✗ |
if (response_id == GTK_RESPONSE_OK) |
940 |
|
|
{ |
941 |
|
✗ |
new_printer = pp_new_printer_dialog_get_new_printer (pp_new_printer_dialog); |
942 |
|
✗ |
g_object_get(G_OBJECT (new_printer), "name", &self->new_printer_name, NULL); |
943 |
|
|
|
944 |
|
✗ |
actualize_printers_list (self); |
945 |
|
|
|
946 |
|
✗ |
pp_new_printer_add_async (new_printer, |
947 |
|
|
cc_panel_get_cancellable (CC_PANEL (self)), |
948 |
|
|
printer_add_async_cb, |
949 |
|
|
self); |
950 |
|
|
} |
951 |
|
|
|
952 |
|
✗ |
gtk_window_destroy (GTK_WINDOW (pp_new_printer_dialog)); |
953 |
|
✗ |
self->pp_new_printer_dialog = NULL; |
954 |
|
✗ |
} |
955 |
|
|
|
956 |
|
|
static void |
957 |
|
✗ |
printer_add_cb (CcPrintersPanel *self) |
958 |
|
|
{ |
959 |
|
|
GtkNative *native; |
960 |
|
|
|
961 |
|
✗ |
native = gtk_widget_get_native (GTK_WIDGET (self)); |
962 |
|
✗ |
self->pp_new_printer_dialog = pp_new_printer_dialog_new (self->all_ppds_list, |
963 |
|
|
new_printer_dialog_response_cb, |
964 |
|
|
self); |
965 |
|
|
|
966 |
|
✗ |
gtk_window_set_transient_for (GTK_WINDOW (self->pp_new_printer_dialog), |
967 |
|
✗ |
GTK_WINDOW (native)); |
968 |
|
|
|
969 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->pp_new_printer_dialog), TRUE); |
970 |
|
✗ |
} |
971 |
|
|
|
972 |
|
|
static void |
973 |
|
✗ |
update_sensitivity (gpointer user_data) |
974 |
|
|
{ |
975 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
976 |
|
✗ |
const char *cups_server = NULL; |
977 |
|
✗ |
gboolean local_server = TRUE; |
978 |
|
✗ |
gboolean no_cups = FALSE; |
979 |
|
✗ |
gboolean empty_state = FALSE; |
980 |
|
|
|
981 |
|
✗ |
self->is_authorized = |
982 |
|
✗ |
self->permission && |
983 |
|
✗ |
g_permission_get_allowed (G_PERMISSION (self->permission)) && |
984 |
|
✗ |
self->lockdown_settings && |
985 |
|
✗ |
!g_settings_get_boolean (self->lockdown_settings, "disable-print-setup"); |
986 |
|
|
|
987 |
|
✗ |
if (g_strcmp0 (gtk_stack_get_visible_child_name (self->main_stack), "no-cups-page") == 0) |
988 |
|
✗ |
no_cups = TRUE; |
989 |
|
✗ |
else if (g_strcmp0 (gtk_stack_get_visible_child_name (self->main_stack), "empty-state") == 0) |
990 |
|
✗ |
empty_state = TRUE; |
991 |
|
|
|
992 |
|
✗ |
cups_server = cupsServer (); |
993 |
|
✗ |
if (cups_server && |
994 |
|
✗ |
g_ascii_strncasecmp (cups_server, "localhost", 9) != 0 && |
995 |
|
✗ |
g_ascii_strncasecmp (cups_server, "127.0.0.1", 9) != 0 && |
996 |
|
✗ |
g_ascii_strncasecmp (cups_server, "::1", 3) != 0 && |
997 |
|
✗ |
cups_server[0] != '/') |
998 |
|
✗ |
local_server = FALSE; |
999 |
|
|
|
1000 |
|
✗ |
gtk_widget_set_visible (self->search_button, !no_cups); |
1001 |
|
✗ |
gtk_widget_set_sensitive (self->search_button, !empty_state); |
1002 |
|
|
|
1003 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->search_bar), !no_cups); |
1004 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->search_bar), !empty_state); |
1005 |
|
|
|
1006 |
|
✗ |
gtk_widget_set_visible (self->printer_add_button, !empty_state); |
1007 |
|
✗ |
gtk_widget_set_sensitive (self->printer_add_button, local_server && self->is_authorized && !no_cups && !self->new_printer_name); |
1008 |
|
|
|
1009 |
|
✗ |
gtk_widget_set_sensitive (self->printer_add_button_empty, local_server && self->is_authorized && !no_cups && !self->new_printer_name); |
1010 |
|
✗ |
} |
1011 |
|
|
|
1012 |
|
|
static void |
1013 |
|
✗ |
on_permission_changed (CcPrintersPanel *self) |
1014 |
|
|
{ |
1015 |
|
✗ |
actualize_printers_list (self); |
1016 |
|
✗ |
update_sensitivity (self); |
1017 |
|
✗ |
} |
1018 |
|
|
|
1019 |
|
|
static void |
1020 |
|
✗ |
on_lockdown_settings_changed (CcPrintersPanel *self, |
1021 |
|
|
const char *key) |
1022 |
|
|
{ |
1023 |
|
✗ |
if (g_str_equal (key, "disable-print-setup") == FALSE) |
1024 |
|
✗ |
return; |
1025 |
|
|
|
1026 |
|
|
#if 0 |
1027 |
|
|
/* FIXME */ |
1028 |
|
|
gtk_widget_set_sensitive (self->lock_button, |
1029 |
|
|
!g_settings_get_boolean (self->lockdown_settings, "disable-print-setup")); |
1030 |
|
|
#endif |
1031 |
|
|
|
1032 |
|
✗ |
on_permission_changed (self); |
1033 |
|
|
} |
1034 |
|
|
|
1035 |
|
|
static void |
1036 |
|
✗ |
cups_status_check_cb (GObject *source_object, |
1037 |
|
|
GAsyncResult *result, |
1038 |
|
|
gpointer user_data) |
1039 |
|
|
{ |
1040 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
1041 |
|
|
gboolean success; |
1042 |
|
|
|
1043 |
|
✗ |
success = pp_cups_connection_test_finish (PP_CUPS (source_object), result, NULL); |
1044 |
|
✗ |
if (success) |
1045 |
|
|
{ |
1046 |
|
✗ |
actualize_printers_list (self); |
1047 |
|
✗ |
attach_to_cups_notifier (self); |
1048 |
|
|
|
1049 |
|
✗ |
g_clear_handle_id (&self->cups_status_check_id, g_source_remove); |
1050 |
|
|
} |
1051 |
|
✗ |
} |
1052 |
|
|
|
1053 |
|
|
static gboolean |
1054 |
|
✗ |
cups_status_check (gpointer user_data) |
1055 |
|
|
{ |
1056 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
1057 |
|
|
|
1058 |
|
✗ |
pp_cups_connection_test_async (self->cups, NULL, cups_status_check_cb, self); |
1059 |
|
|
|
1060 |
|
✗ |
return self->cups_status_check_id != 0; |
1061 |
|
|
} |
1062 |
|
|
|
1063 |
|
|
static void |
1064 |
|
✗ |
connection_test_cb (GObject *source_object, |
1065 |
|
|
GAsyncResult *result, |
1066 |
|
|
gpointer user_data) |
1067 |
|
|
{ |
1068 |
|
|
CcPrintersPanel *self; |
1069 |
|
|
gboolean success; |
1070 |
|
✗ |
g_autoptr(GError) error = NULL; |
1071 |
|
|
|
1072 |
|
✗ |
success = pp_cups_connection_test_finish (PP_CUPS (source_object), result, &error); |
1073 |
|
|
|
1074 |
|
✗ |
if (error != NULL) |
1075 |
|
|
{ |
1076 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1077 |
|
|
{ |
1078 |
|
✗ |
g_warning ("Could not test connection: %s", error->message); |
1079 |
|
|
} |
1080 |
|
|
|
1081 |
|
✗ |
return; |
1082 |
|
|
} |
1083 |
|
|
|
1084 |
|
✗ |
self = CC_PRINTERS_PANEL (user_data); |
1085 |
|
|
|
1086 |
|
✗ |
if (!success) |
1087 |
|
|
{ |
1088 |
|
✗ |
self->cups_status_check_id = |
1089 |
|
✗ |
g_timeout_add_seconds (CUPS_STATUS_CHECK_INTERVAL, cups_status_check, self); |
1090 |
|
|
} |
1091 |
|
|
} |
1092 |
|
|
|
1093 |
|
|
static void |
1094 |
|
✗ |
get_all_ppds_async_cb (PPDList *ppds, |
1095 |
|
|
gpointer user_data) |
1096 |
|
|
{ |
1097 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
1098 |
|
|
|
1099 |
|
✗ |
self->all_ppds_list = ppd_list_copy (ppds); |
1100 |
|
|
|
1101 |
|
✗ |
if (self->pp_new_printer_dialog) |
1102 |
|
✗ |
pp_new_printer_dialog_set_ppd_list (self->pp_new_printer_dialog, |
1103 |
|
|
self->all_ppds_list); |
1104 |
|
✗ |
} |
1105 |
|
|
|
1106 |
|
|
static gboolean |
1107 |
|
✗ |
filter_function (GtkListBoxRow *row, |
1108 |
|
|
gpointer user_data) |
1109 |
|
|
{ |
1110 |
|
✗ |
CcPrintersPanel *self = (CcPrintersPanel*) user_data; |
1111 |
|
✗ |
PpPrinterEntry *entry = PP_PRINTER_ENTRY (row); |
1112 |
|
|
gboolean retval; |
1113 |
|
✗ |
g_autofree gchar *search = NULL; |
1114 |
|
✗ |
g_autofree gchar *name = NULL; |
1115 |
|
✗ |
g_autofree gchar *location = NULL; |
1116 |
|
|
GList *iter; |
1117 |
|
|
const gchar *search_text; |
1118 |
|
|
|
1119 |
|
✗ |
search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_entry)); |
1120 |
|
|
|
1121 |
|
✗ |
if (g_utf8_strlen (search_text, -1) == 0) |
1122 |
|
|
{ |
1123 |
|
✗ |
retval = TRUE; |
1124 |
|
|
} |
1125 |
|
|
else |
1126 |
|
|
{ |
1127 |
|
✗ |
name = cc_util_normalize_casefold_and_unaccent (pp_printer_entry_get_name (entry)); |
1128 |
|
✗ |
location = cc_util_normalize_casefold_and_unaccent (pp_printer_entry_get_location (entry)); |
1129 |
|
|
|
1130 |
|
✗ |
search = cc_util_normalize_casefold_and_unaccent (search_text); |
1131 |
|
|
|
1132 |
|
✗ |
retval = strstr (name, search) != NULL; |
1133 |
|
✗ |
if (location != NULL) |
1134 |
|
✗ |
retval = retval || (strstr (location, search) != NULL); |
1135 |
|
|
} |
1136 |
|
|
|
1137 |
|
✗ |
if (self->deleted_printer_name != NULL && |
1138 |
|
✗ |
g_strcmp0 (self->deleted_printer_name, pp_printer_entry_get_name (entry)) == 0) |
1139 |
|
|
{ |
1140 |
|
✗ |
retval = FALSE; |
1141 |
|
|
} |
1142 |
|
|
|
1143 |
|
✗ |
if (self->deleted_printers != NULL) |
1144 |
|
|
{ |
1145 |
|
✗ |
for (iter = self->deleted_printers; iter != NULL; iter = iter->next) |
1146 |
|
|
{ |
1147 |
|
✗ |
if (g_strcmp0 (iter->data, pp_printer_entry_get_name (entry)) == 0) |
1148 |
|
|
{ |
1149 |
|
✗ |
retval = FALSE; |
1150 |
|
✗ |
break; |
1151 |
|
|
} |
1152 |
|
|
} |
1153 |
|
|
} |
1154 |
|
|
|
1155 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (row), retval); |
1156 |
|
|
|
1157 |
|
✗ |
return retval; |
1158 |
|
|
} |
1159 |
|
|
|
1160 |
|
|
static gint |
1161 |
|
✗ |
sort_function (GtkListBoxRow *row1, |
1162 |
|
|
GtkListBoxRow *row2, |
1163 |
|
|
gpointer user_data) |
1164 |
|
|
{ |
1165 |
|
✗ |
PpPrinterEntry *entry1 = PP_PRINTER_ENTRY (row1); |
1166 |
|
✗ |
PpPrinterEntry *entry2 = PP_PRINTER_ENTRY (row2); |
1167 |
|
|
|
1168 |
|
✗ |
if (pp_printer_entry_get_name (entry1) != NULL) |
1169 |
|
|
{ |
1170 |
|
✗ |
if (pp_printer_entry_get_name (entry2) != NULL) |
1171 |
|
✗ |
return g_ascii_strcasecmp (pp_printer_entry_get_name (entry1), pp_printer_entry_get_name (entry2)); |
1172 |
|
|
else |
1173 |
|
✗ |
return 1; |
1174 |
|
|
} |
1175 |
|
|
else |
1176 |
|
|
{ |
1177 |
|
✗ |
if (pp_printer_entry_get_name (entry2) != NULL) |
1178 |
|
✗ |
return -1; |
1179 |
|
|
else |
1180 |
|
✗ |
return 0; |
1181 |
|
|
} |
1182 |
|
|
} |
1183 |
|
|
|
1184 |
|
|
static void |
1185 |
|
✗ |
cc_printers_panel_class_init (CcPrintersPanelClass *klass) |
1186 |
|
|
{ |
1187 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1188 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
1189 |
|
✗ |
CcPanelClass *panel_class = CC_PANEL_CLASS (klass); |
1190 |
|
|
|
1191 |
|
✗ |
object_class->get_property = cc_printers_panel_get_property; |
1192 |
|
✗ |
object_class->set_property = cc_printers_panel_set_property; |
1193 |
|
✗ |
object_class->constructed = cc_printers_panel_constructed; |
1194 |
|
✗ |
object_class->dispose = cc_printers_panel_dispose; |
1195 |
|
|
|
1196 |
|
✗ |
panel_class->get_help_uri = cc_printers_panel_get_help_uri; |
1197 |
|
|
|
1198 |
|
✗ |
g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); |
1199 |
|
|
|
1200 |
|
✗ |
g_object_class_install_property (object_class, |
1201 |
|
|
PROP_COMPACT, |
1202 |
|
|
g_param_spec_boolean ("compact", |
1203 |
|
|
"compact", |
1204 |
|
|
"compact", |
1205 |
|
|
FALSE, |
1206 |
|
|
G_PARAM_READWRITE)); |
1207 |
|
|
|
1208 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/printers/cc-printers-panel.ui"); |
1209 |
|
|
|
1210 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, content); |
1211 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, main_stack); |
1212 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, notification); |
1213 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, notification_label); |
1214 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, permission_infobar); |
1215 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, printer_add_button); |
1216 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, printer_add_button_empty); |
1217 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, scrolled_window); |
1218 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, search_bar); |
1219 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, search_button); |
1220 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcPrintersPanel, search_entry); |
1221 |
|
|
|
1222 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, printer_add_cb); |
1223 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_printer_deletion_undone); |
1224 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_notification_dismissed); |
1225 |
|
✗ |
} |
1226 |
|
|
|
1227 |
|
|
static void |
1228 |
|
✗ |
cc_printers_panel_init (CcPrintersPanel *self) |
1229 |
|
|
{ |
1230 |
|
✗ |
g_autoptr(GtkCssProvider) provider = NULL; |
1231 |
|
|
|
1232 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
1233 |
|
|
|
1234 |
|
✗ |
g_resources_register (cc_printers_get_resource ()); |
1235 |
|
|
|
1236 |
|
✗ |
provider = gtk_css_provider_new (); |
1237 |
|
✗ |
gtk_css_provider_load_from_resource (provider, |
1238 |
|
|
"/org/gnome/control-center/printers/printers.css"); |
1239 |
|
✗ |
gtk_style_context_add_provider_for_display (gdk_display_get_default (), |
1240 |
|
✗ |
GTK_STYLE_PROVIDER (provider), |
1241 |
|
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); |
1242 |
|
|
|
1243 |
|
|
/* initialize main data structure */ |
1244 |
|
✗ |
self->reference = g_object_new (G_TYPE_OBJECT, NULL); |
1245 |
|
|
|
1246 |
|
✗ |
self->cups = pp_cups_new (); |
1247 |
|
|
|
1248 |
|
✗ |
self->printer_entries = g_hash_table_new_full (g_str_hash, |
1249 |
|
|
g_str_equal, |
1250 |
|
|
g_free, |
1251 |
|
|
NULL); |
1252 |
|
|
|
1253 |
|
✗ |
g_type_ensure (CC_TYPE_PERMISSION_INFOBAR); |
1254 |
|
|
|
1255 |
|
✗ |
g_object_set_data_full (self->reference, "self", self, NULL); |
1256 |
|
|
|
1257 |
|
|
/* connect signals */ |
1258 |
|
✗ |
gtk_list_box_set_filter_func (self->content, |
1259 |
|
|
filter_function, |
1260 |
|
|
self, |
1261 |
|
|
NULL); |
1262 |
|
✗ |
g_signal_connect_swapped (self->search_entry, |
1263 |
|
|
"search-changed", |
1264 |
|
|
G_CALLBACK (gtk_list_box_invalidate_filter), |
1265 |
|
|
self->content); |
1266 |
|
✗ |
gtk_list_box_set_sort_func (self->content, |
1267 |
|
|
sort_function, |
1268 |
|
|
NULL, |
1269 |
|
|
NULL); |
1270 |
|
|
|
1271 |
|
✗ |
self->lockdown_settings = g_settings_new ("org.gnome.desktop.lockdown"); |
1272 |
|
✗ |
if (self->lockdown_settings) |
1273 |
|
✗ |
g_signal_connect_object (self->lockdown_settings, |
1274 |
|
|
"changed", |
1275 |
|
|
G_CALLBACK (on_lockdown_settings_changed), |
1276 |
|
|
self, |
1277 |
|
|
G_CONNECT_SWAPPED | G_CONNECT_AFTER); |
1278 |
|
|
|
1279 |
|
|
/* Add unlock button */ |
1280 |
|
✗ |
self->permission = (GPermission *)polkit_permission_new_sync ( |
1281 |
|
|
"org.opensuse.cupspkhelper.mechanism.all-edit", NULL, NULL, NULL); |
1282 |
|
✗ |
if (self->permission != NULL) |
1283 |
|
|
{ |
1284 |
|
✗ |
g_signal_connect_object (self->permission, |
1285 |
|
|
"notify", |
1286 |
|
|
G_CALLBACK (on_permission_changed), |
1287 |
|
|
self, |
1288 |
|
|
G_CONNECT_SWAPPED | G_CONNECT_AFTER); |
1289 |
|
|
|
1290 |
|
✗ |
cc_permission_infobar_set_permission (self->permission_infobar, |
1291 |
|
|
self->permission); |
1292 |
|
✗ |
cc_permission_infobar_set_title (self->permission_infobar, |
1293 |
|
|
_("Unlock to add printers and change settings")); |
1294 |
|
|
|
1295 |
|
✗ |
on_permission_changed (self); |
1296 |
|
|
} |
1297 |
|
|
else |
1298 |
|
✗ |
g_warning ("Your system does not have the cups-pk-helper's policy \ |
1299 |
|
|
\"org.opensuse.cupspkhelper.mechanism.all-edit\" installed. \ |
1300 |
|
|
Please check your installation"); |
1301 |
|
|
|
1302 |
|
✗ |
self->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); |
1303 |
|
|
|
1304 |
|
✗ |
actualize_printers_list (self); |
1305 |
|
✗ |
attach_to_cups_notifier (self); |
1306 |
|
|
|
1307 |
|
✗ |
get_all_ppds_async (cc_panel_get_cancellable (CC_PANEL (self)), |
1308 |
|
|
get_all_ppds_async_cb, |
1309 |
|
|
self); |
1310 |
|
|
|
1311 |
|
✗ |
pp_cups_connection_test_async (self->cups, cc_panel_get_cancellable (CC_PANEL (self)), connection_test_cb, self); |
1312 |
|
✗ |
} |
1313 |
|
|
|