]> Pileus Git - ~andy/gtk/blob - gtk/gtkprintbackend.c
3c64823ebec71d30e80efa3535f1a3ecb6e0d6d9
[~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 void                 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 void
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
510 static GList *
511 fallback_printer_list_papers (GtkPrinter *printer)
512 {
513   return NULL;
514 }
515
516 static GtkPageSetup *
517 fallback_printer_get_default_page_size (GtkPrinter *printer)
518 {
519   return NULL;
520 }
521
522 static GtkPrintCapabilities
523 fallback_printer_get_capabilities (GtkPrinter *printer)
524 {
525   return 0;
526 }
527
528
529 static void
530 printer_hash_to_sorted_active_list (const gchar  *key,
531                                     gpointer      value,
532                                     GList       **out_list)
533 {
534   GtkPrinter *printer;
535
536   printer = GTK_PRINTER (value);
537
538   if (gtk_printer_get_name (printer) == NULL)
539     return;
540
541   if (!gtk_printer_is_active (printer))
542     return;
543
544   *out_list = g_list_insert_sorted (*out_list, value, (GCompareFunc) gtk_printer_compare);
545 }
546
547
548 void
549 gtk_print_backend_add_printer (GtkPrintBackend *backend,
550                                GtkPrinter      *printer)
551 {
552   GtkPrintBackendPrivate *priv;
553   
554   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
555
556   priv = backend->priv;
557
558   if (!priv->printers)
559     return;
560   
561   g_hash_table_insert (priv->printers,
562                        g_strdup (gtk_printer_get_name (printer)), 
563                        g_object_ref (printer));
564 }
565
566 void
567 gtk_print_backend_remove_printer (GtkPrintBackend *backend,
568                                   GtkPrinter      *printer)
569 {
570   GtkPrintBackendPrivate *priv;
571   
572   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
573   priv = backend->priv;
574
575   if (!priv->printers)
576     return;
577   
578   g_hash_table_remove (priv->printers,
579                        gtk_printer_get_name (printer));
580 }
581
582 void
583 gtk_print_backend_set_list_done (GtkPrintBackend *backend)
584 {
585   if (!backend->priv->printer_list_done)
586     {
587       backend->priv->printer_list_done = TRUE;
588       g_signal_emit (backend, signals[PRINTER_LIST_DONE], 0);
589     }
590 }
591
592
593 GList *
594 gtk_print_backend_get_printer_list (GtkPrintBackend *backend)
595 {
596   GtkPrintBackendPrivate *priv;
597   GList *result;
598   
599   g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
600
601   priv = backend->priv;
602
603   result = NULL;
604   if (priv->printers != NULL)
605     g_hash_table_foreach (priv->printers,
606                           (GHFunc) printer_hash_to_sorted_active_list,
607                           &result);
608
609   if (!priv->printer_list_requested && priv->printers != NULL)
610     {
611       if (GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list)
612         GTK_PRINT_BACKEND_GET_CLASS (backend)->request_printer_list (backend);
613       priv->printer_list_requested = TRUE;
614     }
615
616   return result;
617 }
618
619 gboolean
620 gtk_print_backend_printer_list_is_done (GtkPrintBackend *print_backend)
621 {
622   g_return_val_if_fail (GTK_IS_PRINT_BACKEND (print_backend), TRUE);
623
624   return print_backend->priv->printer_list_done;
625 }
626
627 GtkPrinter *
628 gtk_print_backend_find_printer (GtkPrintBackend *backend,
629                                 const gchar     *printer_name)
630 {
631   GtkPrintBackendPrivate *priv;
632   GtkPrinter *printer;
633   
634   g_return_val_if_fail (GTK_IS_PRINT_BACKEND (backend), NULL);
635
636   priv = backend->priv;
637
638   if (priv->printers)
639     printer = g_hash_table_lookup (priv->printers, printer_name);
640   else
641     printer = NULL;
642
643   return printer;  
644 }
645
646 void
647 gtk_print_backend_print_stream (GtkPrintBackend        *backend,
648                                 GtkPrintJob            *job,
649                                 GIOChannel             *data_io,
650                                 GtkPrintJobCompleteFunc callback,
651                                 gpointer                user_data,
652                                 GDestroyNotify          dnotify)
653 {
654   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
655
656   GTK_PRINT_BACKEND_GET_CLASS (backend)->print_stream (backend,
657                                                        job,
658                                                        data_io,
659                                                        callback,
660                                                        user_data,
661                                                        dnotify);
662 }
663
664 void 
665 gtk_print_backend_set_password (GtkPrintBackend  *backend,
666                                 gchar           **auth_info_required,
667                                 gchar           **auth_info)
668 {
669   g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
670
671   if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
672     GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend, auth_info_required, auth_info);
673 }
674
675 static void
676 store_entry (GtkEntry  *entry,
677              gpointer   user_data)
678 {
679   gchar **data = (gchar **) user_data;
680
681   if (*data != NULL)
682     {
683       memset (*data, 0, strlen (*data));
684       g_free (*data);
685     }
686
687   *data = g_strdup (gtk_entry_get_text (entry));
688 }
689
690 static void
691 password_dialog_response (GtkWidget       *dialog,
692                           gint             response_id,
693                           GtkPrintBackend *backend)
694 {
695   GtkPrintBackendPrivate *priv = backend->priv;
696   gint i;
697
698   if (response_id == GTK_RESPONSE_OK)
699     gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info);
700   else
701     gtk_print_backend_set_password (backend, priv->auth_info_required, NULL);
702
703   for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
704     if (priv->auth_info[i] != NULL)
705       {
706         memset (priv->auth_info[i], 0, strlen (priv->auth_info[i]));
707         g_free (priv->auth_info[i]);
708         priv->auth_info[i] = NULL;
709       }
710   g_free (priv->auth_info);
711   priv->auth_info = NULL;
712
713   g_strfreev (priv->auth_info_required);
714
715   gtk_widget_destroy (dialog);
716
717   g_object_unref (backend);
718 }
719
720 static void
721 request_password (GtkPrintBackend  *backend,
722                   gpointer          auth_info_required,
723                   gpointer          auth_info_default,
724                   gpointer          auth_info_display,
725                   gpointer          auth_info_visible,
726                   const gchar      *prompt)
727 {
728   GtkPrintBackendPrivate *priv = backend->priv;
729   GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry;
730   GtkWidget *focus = NULL;
731   gchar     *markup;
732   gint       length;
733   gint       i;
734   gchar    **ai_required = (gchar **) auth_info_required;
735   gchar    **ai_default = (gchar **) auth_info_default;
736   gchar    **ai_display = (gchar **) auth_info_display;
737   gboolean  *ai_visible = (gboolean *) auth_info_visible;
738
739   priv->auth_info_required = g_strdupv (ai_required);
740   length = g_strv_length (ai_required);
741   priv->auth_info = g_new0 (gchar *, length);
742
743   dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL, 
744                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
745                                          GTK_STOCK_OK, GTK_RESPONSE_OK,
746                                          NULL);
747
748   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
749   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
750
751   main_box = gtk_hbox_new (FALSE, 0);
752
753   /* Left */
754   icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
755   gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
756   gtk_misc_set_padding (GTK_MISC (icon), 6, 6);
757
758
759   /* Right */
760   vbox = gtk_vbox_new (FALSE, 0);
761   gtk_widget_set_size_request (GTK_WIDGET (vbox), 320, -1);
762
763   /* Right - 1. */
764   label = gtk_label_new (NULL);
765   markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"large\">%s</span>", prompt);
766   gtk_label_set_markup (GTK_LABEL (label), markup);
767   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
768   gtk_widget_set_size_request (GTK_WIDGET (label), 320, -1);
769   g_free (markup);
770
771
772   /* Packing */
773   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), main_box, TRUE, FALSE, 0);
774
775   gtk_box_pack_start (GTK_BOX (main_box), icon, FALSE, FALSE, 6);
776   gtk_box_pack_start (GTK_BOX (main_box), vbox, FALSE, FALSE, 6);
777
778   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 6);
779   
780   /* Right - 2. */
781   for (i = 0; i < length; i++)
782     {
783       priv->auth_info[i] = g_strdup (ai_default[i]);
784       if (ai_display[i] != NULL)
785         {
786           box = gtk_hbox_new (TRUE, 0);
787
788           label = gtk_label_new (ai_display[i]);
789           gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
790
791           entry = gtk_entry_new ();
792           focus = entry;
793
794           if (ai_default[i] != NULL)
795             gtk_entry_set_text (GTK_ENTRY (entry), ai_default[i]);
796
797           gtk_entry_set_visibility (GTK_ENTRY (entry), ai_visible[i]);
798           gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
799
800           gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, TRUE, 6);
801
802           gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
803           gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 0);
804
805           g_signal_connect (entry, "changed",
806                             G_CALLBACK (store_entry), &(priv->auth_info[i]));
807         }
808     }
809
810   if (focus != NULL)
811     {
812       gtk_widget_grab_focus (focus);
813       focus = NULL;
814     }
815
816   g_object_ref (backend);
817   g_signal_connect (G_OBJECT (dialog), "response",
818                     G_CALLBACK (password_dialog_response), backend);
819
820   gtk_widget_show_all (dialog);
821 }
822
823 void
824 gtk_print_backend_destroy (GtkPrintBackend *print_backend)
825 {
826   /* The lifecycle of print backends and printers are tied, such that
827    * the backend owns the printers, but the printers also ref the backend.
828    * This is so that if the app has a reference to a printer its backend
829    * will be around. However, this results in a cycle, which we break
830    * with this call, which causes the print backend to release its printers.
831    */
832   g_object_run_dispose (G_OBJECT (print_backend));
833 }
834
835
836 #define __GTK_PRINT_BACKEND_C__
837 #include "gtkaliasdef.c"