]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintbackend.c
Revert "Default to hard margins not available"
[~andy/gtk] / gtk / gtkprintbackend.c
1 /* GTK - The GIMP Toolkit
2  * gtkprintbackend.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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #include <string.h>
23
24 #include <gmodule.h>
25
26 #include "gtkintl.h"
27 #include "gtkmodules.h"
28 #include "gtkmarshalers.h"
29 #include "gtkprivate.h"
30 #include "gtkprintbackend.h"
31 #include "gtkprinter-private.h"
32 #include "gtkalias.h"
33
34 #define GTK_PRINT_BACKEND_GET_PRIVATE(o)  \
35    (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PRINT_BACKEND, GtkPrintBackendPrivate))
36
37 static void gtk_print_backend_dispose      (GObject      *object);
38 static void gtk_print_backend_set_property (GObject      *object,
39                                             guint         prop_id,
40                                             const GValue *value,
41                                             GParamSpec   *pspec);
42 static void gtk_print_backend_get_property (GObject      *object,
43                                             guint         prop_id,
44                                             GValue       *value,
45                                             GParamSpec   *pspec);
46
47 struct _GtkPrintBackendPrivate
48 {
49   GHashTable *printers;
50   guint printer_list_requested : 1;
51   guint printer_list_done : 1;
52   GtkPrintBackendStatus status;
53   char **auth_info_required;
54   char **auth_info;
55 };
56
57 enum {
58   PRINTER_LIST_CHANGED,
59   PRINTER_LIST_DONE,
60   PRINTER_ADDED,
61   PRINTER_REMOVED,
62   PRINTER_STATUS_CHANGED,
63   REQUEST_PASSWORD,
64   LAST_SIGNAL
65 };
66
67 static guint signals[LAST_SIGNAL] = { 0 };
68
69 enum 
70
71   PROP_ZERO,
72   PROP_STATUS
73 };
74
75 static GObjectClass *backend_parent_class;
76
77 GQuark
78 gtk_print_backend_error_quark (void)
79 {
80   static GQuark quark = 0;
81   if (quark == 0)
82     quark = g_quark_from_static_string ("gtk-print-backend-error-quark");
83   return quark;
84 }
85
86 /*****************************************
87  *     GtkPrintBackendModule modules     *
88  *****************************************/
89
90 typedef struct _GtkPrintBackendModule GtkPrintBackendModule;
91 typedef struct _GtkPrintBackendModuleClass GtkPrintBackendModuleClass;
92
93 struct _GtkPrintBackendModule
94 {
95   GTypeModule parent_instance;
96   
97   GModule *library;
98
99   void             (*init)     (GTypeModule    *module);
100   void             (*exit)     (void);
101   GtkPrintBackend* (*create)   (void);
102
103   gchar *path;
104 };
105
106 struct _GtkPrintBackendModuleClass
107 {
108   GTypeModuleClass parent_class;
109 };
110
111 G_DEFINE_TYPE (GtkPrintBackendModule, _gtk_print_backend_module, G_TYPE_TYPE_MODULE)
112 #define GTK_TYPE_PRINT_BACKEND_MODULE      (_gtk_print_backend_module_get_type ())
113 #define GTK_PRINT_BACKEND_MODULE(module)   (G_TYPE_CHECK_INSTANCE_CAST ((module), GTK_TYPE_PRINT_BACKEND_MODULE, GtkPrintBackendModule))
114
115 static GSList *loaded_backends;
116
117 static gboolean
118 gtk_print_backend_module_load (GTypeModule *module)
119 {
120   GtkPrintBackendModule *pb_module = GTK_PRINT_BACKEND_MODULE (module); 
121   gpointer initp, exitp, createp;
122  
123   pb_module->library = g_module_open (pb_module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
124   if (!pb_module->library)
125     {
126       g_warning ("%s", g_module_error());
127       return FALSE;
128     }
129   
130   /* extract symbols from the lib */
131   if (!g_module_symbol (pb_module->library, "pb_module_init",
132                         &initp) ||
133       !g_module_symbol (pb_module->library, "pb_module_exit", 
134                         &exitp) ||
135       !g_module_symbol (pb_module->library, "pb_module_create", 
136                         &createp))
137     {
138       g_warning ("%s", g_module_error());
139       g_module_close (pb_module->library);
140       
141       return FALSE;
142     }
143
144   pb_module->init = initp;
145   pb_module->exit = exitp;
146   pb_module->create = createp;
147
148   /* call the printbackend's init function to let it */
149   /* setup anything it needs to set up. */
150   pb_module->init (module);
151
152   return TRUE;
153 }
154
155 static void
156 gtk_print_backend_module_unload (GTypeModule *module)
157 {
158   GtkPrintBackendModule *pb_module = GTK_PRINT_BACKEND_MODULE (module);
159   
160   pb_module->exit();
161
162   g_module_close (pb_module->library);
163   pb_module->library = NULL;
164
165   pb_module->init = NULL;
166   pb_module->exit = NULL;
167   pb_module->create = NULL;
168 }
169
170 /* This only will ever be called if an error occurs during
171  * initialization
172  */
173 static void
174 gtk_print_backend_module_finalize (GObject *object)
175 {
176   GtkPrintBackendModule *module = GTK_PRINT_BACKEND_MODULE (object);
177
178   g_free (module->path);
179
180   G_OBJECT_CLASS (_gtk_print_backend_module_parent_class)->finalize (object);
181 }
182
183 static void
184 _gtk_print_backend_module_class_init (GtkPrintBackendModuleClass *class)
185 {
186   GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
187   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
188
189   module_class->load = gtk_print_backend_module_load;
190   module_class->unload = gtk_print_backend_module_unload;
191
192   gobject_class->finalize = gtk_print_backend_module_finalize;
193 }
194
195 static void 
196 gtk_print_backend_set_property (GObject      *object,
197                                 guint         prop_id,
198                                 const GValue *value,
199                                 GParamSpec   *pspec)
200 {
201   GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
202   GtkPrintBackendPrivate *priv;
203
204   priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
205
206   switch (prop_id)
207     {
208     case PROP_STATUS:
209       priv->status = g_value_get_int (value);
210       break;
211     default:
212       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
213       break;
214     }
215 }
216
217 static void 
218 gtk_print_backend_get_property (GObject    *object,
219                                 guint       prop_id,
220                                 GValue     *value,
221                                 GParamSpec *pspec)
222 {
223   GtkPrintBackend *backend = GTK_PRINT_BACKEND (object);
224   GtkPrintBackendPrivate *priv;
225
226   priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
227
228   switch (prop_id)
229     {
230     case PROP_STATUS:
231       g_value_set_int (value, priv->status);
232       break;
233     default:
234       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
235       break;
236     }
237 }
238
239 static void
240 _gtk_print_backend_module_init (GtkPrintBackendModule *pb_module)
241 {
242 }
243
244 static GtkPrintBackend *
245 _gtk_print_backend_module_create (GtkPrintBackendModule *pb_module)
246 {
247   GtkPrintBackend *pb;
248   
249   if (g_type_module_use (G_TYPE_MODULE (pb_module)))
250     {
251       pb = pb_module->create ();
252       g_type_module_unuse (G_TYPE_MODULE (pb_module));
253       return pb;
254     }
255   return NULL;
256 }
257
258 static GtkPrintBackend *
259 _gtk_print_backend_create (const gchar *backend_name)
260 {
261   GSList *l;
262   gchar *module_path;
263   gchar *full_name;
264   GtkPrintBackendModule *pb_module;
265   GtkPrintBackend *pb;
266
267   for (l = loaded_backends; l != NULL; l = l->next)
268     {
269       pb_module = l->data;
270       
271       if (strcmp (G_TYPE_MODULE (pb_module)->name, backend_name) == 0)
272         return _gtk_print_backend_module_create (pb_module);
273     }
274
275   pb = NULL;
276   if (g_module_supported ())
277     {
278       full_name = g_strconcat ("printbackend-", backend_name, NULL);
279       module_path = _gtk_find_module (full_name, "printbackends");
280       g_free (full_name);
281
282       if (module_path)
283         {
284           pb_module = g_object_new (GTK_TYPE_PRINT_BACKEND_MODULE, NULL);
285
286           g_type_module_set_name (G_TYPE_MODULE (pb_module), backend_name);
287           pb_module->path = g_strdup (module_path);
288
289           loaded_backends = g_slist_prepend (loaded_backends,
290                                              pb_module);
291
292           pb = _gtk_print_backend_module_create (pb_module);
293
294           /* Increase use-count so that we don't unload print backends.
295            * There is a problem with module unloading in the cups module,
296            * see cups_dispatch_watch_finalize for details. 
297            */
298           g_type_module_use (G_TYPE_MODULE (pb_module));
299         }
300       
301       g_free (module_path);
302     }
303
304   return pb;
305 }
306
307 GList *
308 gtk_print_backend_load_modules (void)
309 {
310   GList *result;
311   GtkPrintBackend *backend;
312   gchar *setting;
313   gchar **backends;
314   gint i;
315   GtkSettings *settings;
316
317   result = NULL;
318
319   settings = gtk_settings_get_default ();
320   if (settings)
321     g_object_get (settings, "gtk-print-backends", &setting, NULL);
322   else
323     setting = g_strdup (GTK_PRINT_BACKENDS);
324
325   backends = g_strsplit (setting, ",", -1);
326
327   for (i = 0; backends[i]; i++)
328     {
329       g_strchug (backends[i]);
330       g_strchomp (backends[i]);
331       backend = _gtk_print_backend_create (backends[i]);
332       
333       if (backend)
334         result = g_list_append (result, backend);
335     }
336
337   g_strfreev (backends);
338   g_free (setting);
339
340   return result;
341 }
342
343 /*****************************************
344  *             GtkPrintBackend           *
345  *****************************************/
346
347 G_DEFINE_TYPE (GtkPrintBackend, gtk_print_backend, G_TYPE_OBJECT)
348
349 static void                 fallback_printer_request_details       (GtkPrinter          *printer);
350 static gboolean             fallback_printer_mark_conflicts        (GtkPrinter          *printer,
351                                                                     GtkPrinterOptionSet *options);
352 static gboolean             fallback_printer_get_hard_margins      (GtkPrinter          *printer,
353                                                                     gdouble             *top,
354                                                                     gdouble             *bottom,
355                                                                     gdouble             *left,
356                                                                     gdouble             *right);
357 static GList *              fallback_printer_list_papers           (GtkPrinter          *printer);
358 static GtkPageSetup *       fallback_printer_get_default_page_size (GtkPrinter          *printer);
359 static GtkPrintCapabilities fallback_printer_get_capabilities      (GtkPrinter          *printer);
360 static void                 request_password                       (GtkPrintBackend     *backend,
361                                                                     gpointer             auth_info_required,
362                                                                     gpointer             auth_info_default,
363                                                                     gpointer             auth_info_display,
364                                                                     gpointer             auth_info_visible,
365                                                                     const gchar         *prompt);
366   
367 static void
368 gtk_print_backend_class_init (GtkPrintBackendClass *class)
369 {
370   GObjectClass *object_class;
371   object_class = (GObjectClass *) class;
372
373   backend_parent_class = g_type_class_peek_parent (class);
374   
375   object_class->dispose = gtk_print_backend_dispose;
376   object_class->set_property = gtk_print_backend_set_property;
377   object_class->get_property = gtk_print_backend_get_property;
378
379   class->printer_request_details = fallback_printer_request_details;
380   class->printer_mark_conflicts = fallback_printer_mark_conflicts;
381   class->printer_get_hard_margins = fallback_printer_get_hard_margins;
382   class->printer_list_papers = fallback_printer_list_papers;
383   class->printer_get_default_page_size = fallback_printer_get_default_page_size;
384   class->printer_get_capabilities = fallback_printer_get_capabilities;
385   class->request_password = request_password;
386   
387   g_object_class_install_property (object_class, 
388                                    PROP_STATUS,
389                                    g_param_spec_int ("status",
390                                                      "Status",
391                                                      "The status of the print backend",
392                                                      GTK_PRINT_BACKEND_STATUS_UNKNOWN,
393                                                      GTK_PRINT_BACKEND_STATUS_UNAVAILABLE,
394                                                      GTK_PRINT_BACKEND_STATUS_UNKNOWN,
395                                                      GTK_PARAM_READWRITE)); 
396
397   g_type_class_add_private (class, sizeof (GtkPrintBackendPrivate));
398   
399   signals[PRINTER_LIST_CHANGED] =
400     g_signal_new (I_("printer-list-changed"),
401                   G_TYPE_FROM_CLASS (class),
402                   G_SIGNAL_RUN_LAST,
403                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_changed),
404                   NULL, NULL,
405                   g_cclosure_marshal_VOID__VOID,
406                   G_TYPE_NONE, 0);
407   signals[PRINTER_LIST_DONE] =
408     g_signal_new (I_("printer-list-done"),
409                     G_TYPE_FROM_CLASS (class),
410                     G_SIGNAL_RUN_LAST,
411                     G_STRUCT_OFFSET (GtkPrintBackendClass, printer_list_done),
412                     NULL, NULL,
413                     g_cclosure_marshal_VOID__VOID,
414                     G_TYPE_NONE, 0);
415   signals[PRINTER_ADDED] =
416     g_signal_new (I_("printer-added"),
417                   G_TYPE_FROM_CLASS (class),
418                   G_SIGNAL_RUN_LAST,
419                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_added),
420                   NULL, NULL,
421                   g_cclosure_marshal_VOID__OBJECT,
422                   G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
423   signals[PRINTER_REMOVED] =
424     g_signal_new (I_("printer-removed"),
425                   G_TYPE_FROM_CLASS (class),
426                   G_SIGNAL_RUN_LAST,
427                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_removed),
428                   NULL, NULL,
429                   g_cclosure_marshal_VOID__OBJECT,
430                   G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
431   signals[PRINTER_STATUS_CHANGED] =
432     g_signal_new (I_("printer-status-changed"),
433                   G_TYPE_FROM_CLASS (class),
434                   G_SIGNAL_RUN_LAST,
435                   G_STRUCT_OFFSET (GtkPrintBackendClass, printer_status_changed),
436                   NULL, NULL,
437                   g_cclosure_marshal_VOID__OBJECT,
438                   G_TYPE_NONE, 1, GTK_TYPE_PRINTER);
439   signals[REQUEST_PASSWORD] =
440     g_signal_new (I_("request-password"),
441                   G_TYPE_FROM_CLASS (class),
442                   G_SIGNAL_RUN_LAST,
443                   G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
444                   NULL, NULL,
445                   _gtk_marshal_VOID__POINTER_POINTER_POINTER_POINTER_STRING,
446                   G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING);
447 }
448
449 static void
450 gtk_print_backend_init (GtkPrintBackend *backend)
451 {
452   GtkPrintBackendPrivate *priv;
453
454   priv = backend->priv = GTK_PRINT_BACKEND_GET_PRIVATE (backend); 
455
456   priv->printers = g_hash_table_new_full (g_str_hash, g_str_equal, 
457                                           (GDestroyNotify) g_free,
458                                           (GDestroyNotify) g_object_unref);
459   priv->auth_info_required = NULL;
460   priv->auth_info = NULL;
461 }
462
463 static void
464 gtk_print_backend_dispose (GObject *object)
465 {
466   GtkPrintBackend *backend;
467   GtkPrintBackendPrivate *priv;
468
469   backend = GTK_PRINT_BACKEND (object);
470   priv = backend->priv;
471
472   /* We unref the printers in dispose, not in finalize so that
473    * we can break refcount cycles with gtk_print_backend_destroy 
474    */
475   if (priv->printers)
476     {
477       g_hash_table_destroy (priv->printers);
478       priv->printers = NULL;
479     }
480
481   backend_parent_class->dispose (object);
482 }
483
484
485 static void
486 fallback_printer_request_details (GtkPrinter *printer)
487 {
488 }
489
490 static gboolean
491 fallback_printer_mark_conflicts (GtkPrinter          *printer,
492                                  GtkPrinterOptionSet *options)
493 {
494   return FALSE;
495 }
496
497 static gboolean
498 fallback_printer_get_hard_margins (GtkPrinter *printer,
499                                    gdouble    *top,
500                                    gdouble    *bottom,
501                                    gdouble    *left,
502                                    gdouble    *right)
503 {
504   *top = 0;
505   *bottom = 0;
506   *left = 0;
507   *right = 0;
508
509   return TRUE;
510 }
511
512 static GList *
513 fallback_printer_list_papers (GtkPrinter *printer)
514 {
515   return NULL;
516 }
517
518 static GtkPageSetup *
519 fallback_printer_get_default_page_size (GtkPrinter *printer)
520 {
521   return NULL;
522 }
523
524 static GtkPrintCapabilities
525 fallback_printer_get_capabilities (GtkPrinter *printer)
526 {
527   return 0;
528 }
529
530
531 static void
532 printer_hash_to_sorted_active_list (const gchar  *key,
533                                     gpointer      value,
534                                     GList       **out_list)
535 {
536   GtkPrinter *printer;
537
538   printer = GTK_PRINTER (value);
539
540   if (gtk_printer_get_name (printer) == NULL)
541     return;
542
543   if (!gtk_printer_is_active (printer))
544     return;
545
546   *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
547 }
548
549
550 void
551 gtk_print_backend_add_printer (GtkPrintBackend *backend,
552                                GtkPrinter      *printer)
553 {
554   GtkPrintBackendPrivate *priv;
555   
556   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
557
558   priv = backend->priv;
559
560   if (!priv->printers)
561     return;
562   
563   g_hash_table_insert (priv->printers,
564                        g_strdup (gtk_printer_get_name (printer)), 
565                        g_object_ref (printer));
566 }
567
568 void
569 gtk_print_backend_remove_printer (GtkPrintBackend *backend,
570                                   GtkPrinter      *printer)
571 {
572   GtkPrintBackendPrivate *priv;
573   
574   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
575   priv = backend->priv;
576
577   if (!priv->printers)
578     return;
579   
580   g_hash_table_remove (priv->printers,
581                        gtk_printer_get_name (printer));
582 }
583
584 void
585 gtk_print_backend_set_list_done (GtkPrintBackend *backend)
586 {
587   if (!backend->priv->printer_list_done)
588     {
589       backend->priv->printer_list_done = TRUE;
590       g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
591     }
592 }
593
594
595 GList *
596 gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
597 {
598   GtkPrintBackendPrivate *priv;
599   GList *result;
600   
601   g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
602
603   priv = backend->priv;
604
605   result = NULL;
606   if (priv->printers != NULL)
607     g_hash_table_foreach (priv->printers,
608                           (GHFunc) printer_hash_to_sorted_active_list,
609                           &result);
610
611   if (!priv->printer_list_requested && priv->printers != NULL)
612     {
613       if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
614         GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
615       priv->printer_list_requested = TRUE;
616     }
617
618   return result;
619 }
620
621 gboolean
622 gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
623 {
624   g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
625
626   return print_backend->priv->printer_list_done;
627 }
628
629 GtkPrinter *
630 gtk_print_backend_find_printer (GtkPrintBackend *backend,
631                                 const gchar     *printer_name)
632 {
633   GtkPrintBackendPrivate *priv;
634   GtkPrinter *printer;
635   
636   g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
637
638   priv = backend->priv;
639
640   if (priv->printers)
641     printer = g_hash_table_lookup (priv->printers, printer_name);
642   else
643     printer = NULL;
644
645   return printer;  
646 }
647
648 void
649 gtk_print_backend_print_stream (GtkPrintBackend        *backend,
650                                 GtkPrintJob            *job,
651                                 GIOChannel             *data_io,
652                                 GtkPrintJobCompleteFunc callback,
653                                 gpointer                user_data,
654                                 GDestroyNotify          dnotify)
655 {
656   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
657
658   GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
659                                                        job,
660                                                        data_io,
661                                                        callback,
662                                                        user_data,
663                                                        dnotify);
664 }
665
666 void 
667 gtk_print_backend_set_password (GtkPrintBackend  *backend,
668                                 gchar           **auth_info_required,
669                                 gchar           **auth_info)
670 {
671   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
672
673   if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
674     GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend, auth_info_required, auth_info);
675 }
676
677 static void
678 store_entry (GtkEntry  *entry,
679              gpointer   user_data)
680 {
681   gchar **data = (gchar **) user_data;
682
683   if (*data != NULL)
684     {
685       memset (*data, 0, strlen (*data));
686       g_free (*data);
687     }
688
689   *data = g_strdup (gtk_entry_get_text (entry));
690 }
691
692 static void
693 password_dialog_response (GtkWidget       *dialog,
694                           gint             response_id,
695                           GtkPrintBackend *backend)
696 {
697   GtkPrintBackendPrivate *priv = backend->priv;
698   gint i;
699
700   if (response_id == GTK_RESPONSE_OK)
701     gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info);
702   else
703     gtk_print_backend_set_password (backend, priv->auth_info_required, NULL);
704
705   for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
706     if (priv->auth_info[i] != NULL)
707       {
708         memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
709         g_free (priv->auth_info[i]);
710         priv->auth_info[i] = NULL;
711       }
712   g_free (priv->auth_info);
713   priv->auth_info = NULL;
714
715   g_strfreev (priv->auth_info_required);
716
717   gtk_widget_destroy (dialog);
718
719   g_object_unref (backend);
720 }
721
722 static void
723 request_password (GtkPrintBackend  *backend,
724                   gpointer          auth_info_required,
725                   gpointer          auth_info_default,
726                   gpointer          auth_info_display,
727                   gpointer          auth_info_visible,
728                   const gchar      *prompt)
729 {
730   GtkPrintBackendPrivate *priv = backend->priv;
731   GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry;
732   GtkWidget *focus = NULL;
733   gchar     *markup;
734   gint       length;
735   gint       i;
736   gchar    **ai_required = (gchar **) auth_info_required;
737   gchar    **ai_default = (gchar **) auth_info_default;
738   gchar    **ai_display = (gchar **) auth_info_display;
739   gboolean  *ai_visible = (gboolean *) auth_info_visible;
740
741   priv->auth_info_required = g_strdupv (ai_required);
742   length = g_strv_length (ai_required);
743   priv->auth_info = g_new0 (gchar *, length);
744
745   dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL, 
746                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
747                                          GTK_STOCK_OK, GTK_RESPONSE_OK,
748                                          NULL);
749
750   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
751   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
752
753   main_box = gtk_hbox_new (FALSE, 0);
754
755   /* Left */
756   icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
757   gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
758   gtk_misc_set_padding (GTK_MISC (icon), 6, 6);
759
760
761   /* Right */
762   vbox = gtk_vbox_new (FALSE, 0);
763   gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
764
765   /* Right - 1. */
766   label = gtk_label_new (NULL);
767   markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"large\">%s</span>", prompt);
768   gtk_label_set_markup (GTK_LABEL (label), markup);
769   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
770   gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
771   g_free (markup);
772
773
774   /* Packing */
775   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_box, TRUE, FALSE, 0);
776
777   gtk_box_pack_start (GTK_BOX (main_box), icon, FALSE, FALSE, 6);
778   gtk_box_pack_start (GTK_BOX (main_box), vbox, FALSE, FALSE, 6);
779
780   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 6);
781   
782   /* Right - 2. */
783   for (i = 0; i < length; i++)
784     {
785       priv->auth_info[i] = g_strdup (ai_default[i]);
786       if (ai_display[i] != NULL)
787         {
788           box = gtk_hbox_new (TRUE, 0);
789
790           label = gtk_label_new (ai_display[i]);
791           gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
792
793           entry = gtk_entry_new ();
794           focus = entry;
795
796           if (ai_default[i] != NULL)
797             gtk_entry_set_text (GTK_ENTRY (entry), ai_default[i]);
798
799           gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
800           gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
801
802           gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 6);
803
804           gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
805           gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
806
807           g_signal_connect (entry, "changed",
808                             G_CALLBACK (store_entry), &(priv->auth_info[i]));
809         }
810     }
811
812   if (focus != NULL)
813     {
814       gtk_widget_grab_focus (focus);
815       focus = NULL;
816     }
817
818   g_object_ref (backend);
819   g_signal_connect (G_OBJECT (dialog), "response",
820                     G_CALLBACK (password_dialog_response), backend);
821
822   gtk_widget_show_all (dialog);
823 }
824
825 void
826 gtk_print_backend_destroy (GtkPrintBackend *print_backend)
827 {
828   /* The lifecycle of print backends and printers are tied, such that
829    * the backend owns the printers, but the printers also ref the backend.
830    * This is so that if the app has a reference to a printer its backend
831    * will be around. However, this results in a cycle, which we break
832    * with this call, which causes the print backend to release its printers.
833    */
834   g_object_run_dispose (G_OBJECT (print_backend));
835 }
836
837
838 #define __GTK_PRINT_BACKEND_C__
839 #include "gtkaliasdef.c"