1/* GTK - The GIMP Toolkit
2 * gtkprintbackendprivate.h: Abstract printer backend interfaces
3 * Copyright (C) 2003, Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "config.h"
20#include <string.h>
21
22#include <gmodule.h>
23
24#include "gtkintl.h"
25#include "gtkdebug.h"
26#include "gtkmodulesprivate.h"
27#include "gtkmarshalers.h"
28#include "gtkprivate.h"
29#include "gtkprintbackendprivate.h"
30
31
32static void gtk_print_backend_finalize (GObject *object);
33static void gtk_print_backend_dispose (GObject *object);
34static void gtk_print_backend_set_property (GObject *object,
35 guint prop_id,
36 const GValue *value,
37 GParamSpec *pspec);
38static void gtk_print_backend_get_property (GObject *object,
39 guint prop_id,
40 GValue *value,
41 GParamSpec *pspec);
42
43struct _GtkPrintBackendPrivate
44{
45 GListStore *printers;
46 guint printer_list_requested : 1;
47 guint printer_list_done : 1;
48 GtkPrintBackendStatus status;
49 char **auth_info_required;
50 char **auth_info;
51 gboolean store_auth_info;
52};
53
54enum {
55 PRINTER_LIST_CHANGED,
56 PRINTER_LIST_DONE,
57 PRINTER_ADDED,
58 PRINTER_REMOVED,
59 PRINTER_STATUS_CHANGED,
60 REQUEST_PASSWORD,
61 LAST_SIGNAL
62};
63
64static guint signals[LAST_SIGNAL] = { 0 };
65
66enum
67{
68 PROP_ZERO,
69 PROP_STATUS
70};
71
72static GObjectClass *backend_parent_class;
73
74GQuark
75gtk_print_backend_error_quark (void)
76{
77 static GQuark quark = 0;
78 if (quark == 0)
79 quark = g_quark_from_static_string (string: "gtk-print-backend-error-quark");
80 return quark;
81}
82
83void
84gtk_print_backends_init (void)
85{
86 GIOExtensionPoint *ep;
87 GIOModuleScope *scope;
88 char **paths;
89 int i;
90
91 GTK_NOTE (MODULES,
92 g_print ("Registering extension point %s\n", GTK_PRINT_BACKEND_EXTENSION_POINT_NAME));
93
94 ep = g_io_extension_point_register (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
95 g_io_extension_point_set_required_type (extension_point: ep, GTK_TYPE_PRINT_BACKEND);
96
97 scope = g_io_module_scope_new (flags: G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
98
99 paths = _gtk_get_module_path (type: "printbackends");
100 for (i = 0; paths[i]; i++)
101 {
102 GTK_NOTE (MODULES,
103 g_print ("Scanning io modules in %s\n", paths[i]));
104 g_io_modules_scan_all_in_directory_with_scope (dirname: paths[i], scope);
105 }
106 g_strfreev (str_array: paths);
107
108 g_io_module_scope_free (scope);
109
110 if (GTK_DEBUG_CHECK (MODULES))
111 {
112 GList *list, *l;
113
114 list = g_io_extension_point_get_extensions (extension_point: ep);
115 for (l = list; l; l = l->next)
116 {
117 GIOExtension *ext = l->data;
118 g_print (format: "extension: %s: type %s\n",
119 g_io_extension_get_name (extension: ext),
120 g_type_name (type: g_io_extension_get_type (extension: ext)));
121 }
122 }
123}
124
125/**
126 * gtk_print_backend_load_modules:
127 *
128 * Returns: (element-type GtkPrintBackend) (transfer container):
129 */
130GList *
131gtk_print_backend_load_modules (void)
132{
133 GList *result;
134 GtkPrintBackend *backend;
135 char *setting;
136 char **backends;
137 int i;
138 GtkSettings *settings;
139 GIOExtensionPoint *ep;
140
141 result = NULL;
142
143 ep = g_io_extension_point_lookup (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME);
144
145 settings = gtk_settings_get_default ();
146 if (settings)
147 g_object_get (object: settings, first_property_name: "gtk-print-backends", &setting, NULL);
148 else
149 setting = g_strdup (GTK_PRINT_BACKENDS);
150
151 backends = g_strsplit (string: setting, delimiter: ",", max_tokens: -1);
152
153 for (i = 0; backends[i]; i++)
154 {
155 GIOExtension *ext;
156 GType type;
157
158 ext = g_io_extension_point_get_extension_by_name (extension_point: ep, name: backends[i]);
159 if (!ext)
160 continue;
161
162 GTK_NOTE (PRINTING,
163 g_print ("Found %s print backend\n", backends[i]));
164
165 type = g_io_extension_get_type (extension: ext);
166 backend = g_object_new (object_type: type, NULL);
167 result = g_list_append (list: result, data: backend);
168 }
169
170 g_strfreev (str_array: backends);
171 g_free (mem: setting);
172
173 return result;
174}
175
176/*****************************************
177 * GtkPrintBackend *
178 *****************************************/
179
180G_DEFINE_TYPE_WITH_PRIVATE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
181
182static void fallback_printer_request_details (GtkPrinter *printer);
183static gboolean fallback_printer_mark_conflicts (GtkPrinter *printer,
184 GtkPrinterOptionSet *options);
185static gboolean fallback_printer_get_hard_margins (GtkPrinter *printer,
186 double *top,
187 double *bottom,
188 double *left,
189 double *right);
190static gboolean fallback_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
191 GtkPaperSize *paper_size,
192 double *top,
193 double *bottom,
194 double *left,
195 double *right);
196static GList * fallback_printer_list_papers (GtkPrinter *printer);
197static GtkPageSetup * fallback_printer_get_default_page_size (GtkPrinter *printer);
198static GtkPrintCapabilities fallback_printer_get_capabilities (GtkPrinter *printer);
199static void request_password (GtkPrintBackend *backend,
200 gpointer auth_info_required,
201 gpointer auth_info_default,
202 gpointer auth_info_display,
203 gpointer auth_info_visible,
204 const char *prompt,
205 gboolean can_store_auth_info);
206
207static void
208gtk_print_backend_set_property (GObject *object,
209 guint prop_id,
210 const GValue *value,
211 GParamSpec *pspec)
212{
213 GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
214 GtkPrintBackendPrivate *priv = backend->priv;
215
216 switch (prop_id)
217 {
218 case PROP_STATUS:
219 priv->status = g_value_get_int (value);
220 break;
221 default:
222 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223 break;
224 }
225}
226
227static void
228gtk_print_backend_get_property (GObject *object,
229 guint prop_id,
230 GValue *value,
231 GParamSpec *pspec)
232{
233 GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
234 GtkPrintBackendPrivate *priv = backend->priv;
235
236 switch (prop_id)
237 {
238 case PROP_STATUS:
239 g_value_set_int (value, v_int: priv->status);
240 break;
241 default:
242 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
243 break;
244 }
245}
246
247static void
248gtk_print_backend_class_init (GtkPrintBackendClass *class)
249{
250 GObjectClass *object_class;
251 object_class = (GObjectClass *) class;
252
253 backend_parent_class = g_type_class_peek_parent (g_class: class);
254
255 object_class->finalize = gtk_print_backend_finalize;
256 object_class->dispose = gtk_print_backend_dispose;
257 object_class->set_property = gtk_print_backend_set_property;
258 object_class->get_property = gtk_print_backend_get_property;
259
260 class->printer_request_details = fallback_printer_request_details;
261 class->printer_mark_conflicts = fallback_printer_mark_conflicts;
262 class->printer_get_hard_margins = fallback_printer_get_hard_margins;
263 class->printer_get_hard_margins_for_paper_size = fallback_printer_get_hard_margins_for_paper_size;
264 class->printer_list_papers = fallback_printer_list_papers;
265 class->printer_get_default_page_size = fallback_printer_get_default_page_size;
266 class->printer_get_capabilities = fallback_printer_get_capabilities;
267 class->request_password = request_password;
268
269 g_object_class_install_property (oclass: object_class,
270 property_id: PROP_STATUS,
271 pspec: g_param_spec_int (name: "status",
272 nick: "Status",
273 blurb: "The status of the print backend",
274 minimum: GTK_PRINT_BACKEND_STATUS_UNKNOWN,
275 maximum: GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
276 default_value: GTK_PRINT_BACKEND_STATUS_UNKNOWN,
277 GTK_PARAM_READWRITE));
278
279 signals[PRINTER_LIST_CHANGED] =
280 g_signal_new (I_("printer-list-changed"),
281 G_TYPE_FROM_CLASS (class),
282 signal_flags: G_SIGNAL_RUN_LAST,
283 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
284 NULL, NULL,
285 NULL,
286 G_TYPE_NONE, n_params: 0);
287 signals[PRINTER_LIST_DONE] =
288 g_signal_new (I_("printer-list-done"),
289 G_TYPE_FROM_CLASS (class),
290 signal_flags: G_SIGNAL_RUN_LAST,
291 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
292 NULL, NULL,
293 NULL,
294 G_TYPE_NONE, n_params: 0);
295 signals[PRINTER_ADDED] =
296 g_signal_new (I_("printer-added"),
297 G_TYPE_FROM_CLASS (class),
298 signal_flags: G_SIGNAL_RUN_LAST,
299 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
300 NULL, NULL,
301 NULL,
302 G_TYPE_NONE, n_params: 1, GTK_TYPE_PRINTER);
303 signals[PRINTER_REMOVED] =
304 g_signal_new (I_("printer-removed"),
305 G_TYPE_FROM_CLASS (class),
306 signal_flags: G_SIGNAL_RUN_LAST,
307 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
308 NULL, NULL,
309 NULL,
310 G_TYPE_NONE, n_params: 1, GTK_TYPE_PRINTER);
311 signals[PRINTER_STATUS_CHANGED] =
312 g_signal_new (I_("printer-status-changed"),
313 G_TYPE_FROM_CLASS (class),
314 signal_flags: G_SIGNAL_RUN_LAST,
315 G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
316 NULL, NULL,
317 NULL,
318 G_TYPE_NONE, n_params: 1, GTK_TYPE_PRINTER);
319 signals[REQUEST_PASSWORD] =
320 g_signal_new (I_("request-password"),
321 G_TYPE_FROM_CLASS (class),
322 signal_flags: G_SIGNAL_RUN_LAST,
323 G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
324 NULL, NULL, NULL,
325 G_TYPE_NONE, n_params: 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER,
326 G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
327}
328
329static void
330gtk_print_backend_init (GtkPrintBackend *backend)
331{
332 GtkPrintBackendPrivate *priv;
333
334 priv = backend->priv = gtk_print_backend_get_instance_private (self: backend);
335
336 priv->printers = g_list_store_new (GTK_TYPE_PRINTER);
337 priv->auth_info_required = NULL;
338 priv->auth_info = NULL;
339}
340
341static void
342gtk_print_backend_dispose (GObject *object)
343{
344 GtkPrintBackend *backend;
345 GtkPrintBackendPrivate *priv;
346
347 backend = GTK_PRINT_BACKEND (object);
348 priv = backend->priv;
349
350 /* We unref the printers in dispose, not in finalize so that
351 * we can break refcount cycles with gtk_print_backend_destroy
352 */
353 g_list_store_remove_all (store: priv->printers);
354
355 backend_parent_class->dispose (object);
356}
357
358static void
359gtk_print_backend_finalize (GObject *object)
360{
361 GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
362 GtkPrintBackendPrivate *priv = backend->priv;
363
364 g_clear_object (&priv->printers);
365
366 backend_parent_class->finalize (object);
367}
368
369static void
370fallback_printer_request_details (GtkPrinter *printer)
371{
372}
373
374static gboolean
375fallback_printer_mark_conflicts (GtkPrinter *printer,
376 GtkPrinterOptionSet *options)
377{
378 return FALSE;
379}
380
381static gboolean
382fallback_printer_get_hard_margins (GtkPrinter *printer,
383 double *top,
384 double *bottom,
385 double *left,
386 double *right)
387{
388 return FALSE;
389}
390
391static gboolean
392fallback_printer_get_hard_margins_for_paper_size (GtkPrinter *printer,
393 GtkPaperSize *paper_size,
394 double *top,
395 double *bottom,
396 double *left,
397 double *right)
398{
399 return FALSE;
400}
401
402static GList *
403fallback_printer_list_papers (GtkPrinter *printer)
404{
405 return NULL;
406}
407
408static GtkPageSetup *
409fallback_printer_get_default_page_size (GtkPrinter *printer)
410{
411 return NULL;
412}
413
414static GtkPrintCapabilities
415fallback_printer_get_capabilities (GtkPrinter *printer)
416{
417 return 0;
418}
419
420void
421gtk_print_backend_add_printer (GtkPrintBackend *backend,
422 GtkPrinter *printer)
423{
424 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
425
426 g_list_store_append (store: backend->priv->printers, item: printer);
427}
428
429void
430gtk_print_backend_remove_printer (GtkPrintBackend *backend,
431 GtkPrinter *printer)
432{
433 guint position;
434
435 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
436
437 if (g_list_store_find (store: backend->priv->printers, item: printer, position: &position))
438 g_list_store_remove (store: backend->priv->printers, position);
439}
440
441void
442gtk_print_backend_set_list_done (GtkPrintBackend *backend)
443{
444 if (!backend->priv->printer_list_done)
445 {
446 backend->priv->printer_list_done = TRUE;
447 g_signal_emit (instance: backend, signal_id: signals[PRINTER_LIST_DONE], detail: 0);
448 }
449}
450
451
452/**
453 * gtk_print_backend_get_printer_list:
454 *
455 * Returns the current list of printers.
456 *
457 * Returns: (element-type GtkPrinter) (transfer container):
458 * A list of `GtkPrinter` objects
459 */
460GList *
461gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
462{
463 GList *result = NULL;
464 guint i;
465
466 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
467
468 for (i = 0; i < g_list_model_get_n_items (list: G_LIST_MODEL (ptr: backend->priv->printers)); i++)
469 {
470 GtkPrinter *printer = g_list_model_get_item (list: G_LIST_MODEL (ptr: backend->priv->printers), position: i);
471 result = g_list_prepend (list: result, data: printer);
472 g_object_unref (object: printer);
473 }
474
475 if (!backend->priv->printer_list_requested)
476 {
477 if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
478 GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
479 backend->priv->printer_list_requested = TRUE;
480 }
481
482 return result;
483}
484
485GListModel *
486gtk_print_backend_get_printers (GtkPrintBackend *backend)
487{
488 if (!backend->priv->printer_list_requested)
489 {
490 if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
491 GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
492 backend->priv->printer_list_requested = TRUE;
493 }
494
495 return G_LIST_MODEL (ptr: backend->priv->printers);
496}
497
498gboolean
499gtk_print_backend_printer_list_is_done (GtkPrintBackend *backend)
500{
501 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), TRUE);
502
503 return backend->priv->printer_list_done;
504}
505
506GtkPrinter *
507gtk_print_backend_find_printer (GtkPrintBackend *backend,
508 const char *printer_name)
509{
510 GtkPrinter *result = NULL;
511 guint i;
512
513 g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
514
515 for (i = 0; !result && i < g_list_model_get_n_items (list: G_LIST_MODEL (ptr: backend->priv->printers)); i++)
516 {
517 GtkPrinter *printer = g_list_model_get_item (list: G_LIST_MODEL (ptr: backend->priv->printers), position: i);
518 if (strcmp (s1: gtk_printer_get_name (printer), s2: printer_name) == 0)
519 result = printer;
520 g_object_unref (object: printer);
521 }
522
523 return result;
524}
525
526void
527gtk_print_backend_print_stream (GtkPrintBackend *backend,
528 GtkPrintJob *job,
529 GIOChannel *data_io,
530 GtkPrintJobCompleteFunc callback,
531 gpointer user_data,
532 GDestroyNotify dnotify)
533{
534 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
535
536 GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
537 job,
538 data_io,
539 callback,
540 user_data,
541 dnotify);
542}
543
544void
545gtk_print_backend_set_password (GtkPrintBackend *backend,
546 char **auth_info_required,
547 char **auth_info,
548 gboolean store_auth_info)
549{
550 g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
551
552 if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
553 GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend,
554 auth_info_required,
555 auth_info,
556 store_auth_info);
557}
558
559static void
560store_auth_info_toggled (GtkCheckButton *chkbtn,
561 gpointer user_data)
562{
563 gboolean *data = (gboolean *) user_data;
564 *data = gtk_check_button_get_active (GTK_CHECK_BUTTON (chkbtn));
565}
566
567static void
568store_entry (GtkEntry *entry,
569 gpointer user_data)
570{
571 char **data = (char **) user_data;
572
573 if (*data != NULL)
574 {
575 memset (s: *data, c: 0, n: strlen (s: *data));
576 g_free (mem: *data);
577 }
578
579 *data = g_strdup (str: gtk_editable_get_text (GTK_EDITABLE (entry)));
580}
581
582static void
583password_dialog_response (GtkWidget *dialog,
584 int response_id,
585 GtkPrintBackend *backend)
586{
587 GtkPrintBackendPrivate *priv = backend->priv;
588 int i, auth_info_len;
589
590 if (response_id == GTK_RESPONSE_OK)
591 gtk_print_backend_set_password (backend, auth_info_required: priv->auth_info_required, auth_info: priv->auth_info, store_auth_info: priv->store_auth_info);
592 else
593 gtk_print_backend_set_password (backend, auth_info_required: priv->auth_info_required, NULL, FALSE);
594
595 /* We want to clear the data before freeing it */
596 auth_info_len = g_strv_length (str_array: priv->auth_info_required);
597 for (i = 0; i < auth_info_len; i++)
598 {
599 if (priv->auth_info[i] != NULL)
600 {
601 memset (s: priv->auth_info[i], c: 0, n: strlen (s: priv->auth_info[i]));
602 g_free (mem: priv->auth_info[i]);
603 priv->auth_info[i] = NULL;
604 }
605 }
606
607 g_clear_pointer (&priv->auth_info, g_free);
608 g_clear_pointer (&priv->auth_info_required, g_strfreev);
609
610 gtk_window_destroy (GTK_WINDOW (dialog));
611
612 g_object_unref (object: backend);
613}
614
615static void
616request_password (GtkPrintBackend *backend,
617 gpointer auth_info_required,
618 gpointer auth_info_default,
619 gpointer auth_info_display,
620 gpointer auth_info_visible,
621 const char *prompt,
622 gboolean can_store_auth_info)
623{
624 GtkPrintBackendPrivate *priv = backend->priv;
625 GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry, *chkbtn;
626 GtkWidget *focus = NULL;
627 GtkWidget *content_area;
628 char *markup;
629 int length;
630 int i;
631 char **ai_required = (char **) auth_info_required;
632 char **ai_default = (char **) auth_info_default;
633 char **ai_display = (char **) auth_info_display;
634 gboolean *ai_visible = (gboolean *) auth_info_visible;
635
636 priv->auth_info_required = g_strdupv (str_array: ai_required);
637 length = g_strv_length (str_array: ai_required);
638 priv->auth_info = g_new0 (char *, length + 1);
639 priv->store_auth_info = FALSE;
640
641 dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, flags: GTK_DIALOG_MODAL,
642 _("_Cancel"), GTK_RESPONSE_CANCEL,
643 _("_OK"), GTK_RESPONSE_OK,
644 NULL);
645
646 gtk_dialog_set_default_response (GTK_DIALOG (dialog), response_id: GTK_RESPONSE_OK);
647
648 main_box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
649
650 /* Left */
651 icon = gtk_image_new_from_icon_name (icon_name: "dialog-password-symbolic");
652 gtk_image_set_icon_size (GTK_IMAGE (icon), icon_size: GTK_ICON_SIZE_LARGE);
653 gtk_widget_set_halign (widget: icon, align: GTK_ALIGN_CENTER);
654 gtk_widget_set_valign (widget: icon, align: GTK_ALIGN_START);
655 gtk_widget_set_margin_start (widget: icon, margin: 12);
656 gtk_widget_set_margin_end (widget: icon, margin: 12);
657 gtk_widget_set_margin_top (widget: icon, margin: 12);
658 gtk_widget_set_margin_bottom (widget: icon, margin: 12);
659
660 /* Right */
661 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
662 gtk_widget_set_size_request (GTK_WIDGET (vbox), width: 320, height: -1);
663
664 /* Right - 1. */
665 label = gtk_label_new (NULL);
666 markup = g_markup_printf_escaped (format: "<span weight=\"bold\" size=\"large\">%s</span>", prompt);
667 gtk_label_set_markup (GTK_LABEL (label), str: markup);
668 gtk_label_set_wrap (GTK_LABEL (label), TRUE);
669 gtk_widget_set_size_request (GTK_WIDGET (label), width: 320, height: -1);
670 g_free (mem: markup);
671
672 /* Packing */
673 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
674 gtk_box_append (GTK_BOX (content_area), child: main_box);
675
676 gtk_box_append (GTK_BOX (main_box), child: icon);
677 gtk_box_append (GTK_BOX (main_box), child: vbox);
678
679 gtk_box_append (GTK_BOX (vbox), child: label);
680
681 /* Right - 2. */
682 for (i = 0; i < length; i++)
683 {
684 priv->auth_info[i] = g_strdup (str: ai_default[i]);
685 if (ai_display[i] != NULL)
686 {
687 box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
688 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
689 gtk_widget_set_margin_top (widget: box, margin: 6);
690 gtk_widget_set_margin_bottom (widget: box, margin: 6);
691
692 label = gtk_label_new (str: ai_display[i]);
693 gtk_widget_set_halign (widget: label, align: GTK_ALIGN_START);
694 gtk_widget_set_valign (widget: label, align: GTK_ALIGN_CENTER);
695
696 entry = gtk_entry_new ();
697 focus = entry;
698
699 if (ai_default[i] != NULL)
700 gtk_editable_set_text (GTK_EDITABLE (entry), text: ai_default[i]);
701
702 gtk_entry_set_visibility (GTK_ENTRY (entry), visible: ai_visible[i]);
703 gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
704
705 gtk_box_append (GTK_BOX (vbox), child: box);
706
707 gtk_box_append (GTK_BOX (box), child: label);
708 gtk_box_append (GTK_BOX (box), child: entry);
709
710 g_signal_connect (entry, "changed",
711 G_CALLBACK (store_entry), &(priv->auth_info[i]));
712 }
713 }
714
715 if (can_store_auth_info)
716 {
717 chkbtn = gtk_check_button_new_with_mnemonic (_("_Remember password"));
718 gtk_widget_set_margin_top (widget: chkbtn, margin: 6);
719 gtk_widget_set_margin_bottom (widget: chkbtn, margin: 6);
720 gtk_check_button_set_active (GTK_CHECK_BUTTON (chkbtn), FALSE);
721 gtk_box_append (GTK_BOX (vbox), child: chkbtn);
722 g_signal_connect (chkbtn, "toggled",
723 G_CALLBACK (store_auth_info_toggled),
724 &(priv->store_auth_info));
725 }
726
727 if (focus != NULL)
728 {
729 gtk_widget_grab_focus (widget: focus);
730 focus = NULL;
731 }
732
733 g_object_ref (backend);
734 g_signal_connect (G_OBJECT (dialog), "response",
735 G_CALLBACK (password_dialog_response), backend);
736
737 gtk_widget_show (widget: dialog);
738}
739
740void
741gtk_print_backend_destroy (GtkPrintBackend *backend)
742{
743 /* The lifecycle of print backends and printers are tied, such that
744 * the backend owns the printers, but the printers also ref the backend.
745 * This is so that if the app has a reference to a printer its backend
746 * will be around. However, this results in a cycle, which we break
747 * with this call, which causes the print backend to release its printers.
748 */
749 g_object_run_dispose (G_OBJECT (backend));
750}
751

source code of gtk/gtk/gtkprintbackend.c