[gtk+] Get duplex option via IPP



commit 493aa4e9b3b7ef673a3f0a7b49a6416e9ad8c5c2
Author: Marek Kasik <mkasik redhat com>
Date:   Fri Oct 10 13:36:30 2014 +0200

    Get duplex option via IPP
    
    Request "sides-supported" and "sides-default" attributes through
    IPP if there is no PPD for selected printer.
    Pass "sides" option with other options in printer_get_options().
    Add function setup_ipp_option() for creating of IPP option
    of given name with passed choices and default value.
    Mark such an option as "is-ipp-option" so we can distinguish it
    later.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=725441

 modules/printbackends/cups/gtkprintbackendcups.c |  290 ++++++++++++++++++++--
 modules/printbackends/cups/gtkprintercups.c      |    5 +
 modules/printbackends/cups/gtkprintercups.h      |    2 +
 3 files changed, 276 insertions(+), 21 deletions(-)
---
diff --git a/modules/printbackends/cups/gtkprintbackendcups.c 
b/modules/printbackends/cups/gtkprintbackendcups.c
index 7cdb43e..db2f555 100644
--- a/modules/printbackends/cups/gtkprintbackendcups.c
+++ b/modules/printbackends/cups/gtkprintbackendcups.c
@@ -360,6 +360,26 @@ gtk_print_backend_cups_class_init (GtkPrintBackendCupsClass *class)
   backend_class->set_password = gtk_print_backend_cups_set_password;
 }
 
+static gboolean
+option_is_ipp_option (GtkPrinterOption *option)
+{
+  gpointer data = g_object_get_data (G_OBJECT (option), "is-ipp-option");
+
+  if (data != NULL)
+    return GPOINTER_TO_UINT (data) != 0;
+  else
+    return FALSE;
+}
+
+static void
+option_set_is_ipp_option (GtkPrinterOption *option,
+                          gboolean          is_ipp_option)
+{
+  g_object_set_data (G_OBJECT (option),
+                     "is-ipp-option",
+                     GUINT_TO_POINTER (is_ipp_option ? 1 : 0));
+}
+
 static cairo_status_t
 _cairo_write_to_cups (void                *closure,
                       const unsigned char *data,
@@ -1891,6 +1911,8 @@ static const char * const printer_attrs_detailed[] =
     "media-right-margin-supported",
     "media-bottom-margin-supported",
     "media-top-margin-supported",
+    "sides-default",
+    "sides-supported",
   };
 
 typedef enum
@@ -1944,6 +1966,8 @@ typedef struct
   float     media_left_margin_default;
   float     media_right_margin_default;
   gboolean  media_margin_default_set;
+  gchar    *sides_default;
+  GList    *sides_supported;
 } PrinterSetupInfo;
 
 static void
@@ -2200,6 +2224,17 @@ cups_printer_handle_attribute (GtkPrintBackendCups *cups_backend,
             }
         }
     }
+  else if (g_strcmp0 (ippGetName (attr), "sides-default") == 0)
+    {
+      info->sides_default = g_strdup (ippGetString (attr, 0, NULL));
+    }
+  else if (g_strcmp0 (ippGetName (attr), "sides-supported") == 0)
+    {
+      for (i = 0; i < ippGetCount (attr); i++)
+        info->sides_supported = g_list_prepend (info->sides_supported, g_strdup (ippGetString (attr, i, 
NULL)));
+
+      info->sides_supported = g_list_reverse (info->sides_supported);
+    }
   else if (g_strcmp0 (ippGetName (attr), "media-default") == 0)
     {
       if (ippGetValueTag (attr) == IPP_TAG_KEYWORD ||
@@ -2606,6 +2641,8 @@ cups_request_printer_info_cb (GtkPrintBackendCups *cups_backend,
               GTK_PRINTER_CUPS (printer)->media_left_margin_default = info->media_left_margin_default;
               GTK_PRINTER_CUPS (printer)->media_right_margin_default = info->media_right_margin_default;
             }
+          GTK_PRINTER_CUPS (printer)->sides_default = info->sides_default;
+          GTK_PRINTER_CUPS (printer)->sides_supported = info->sides_supported;
 
           gtk_printer_set_has_details (printer, TRUE);
           g_signal_emit_by_name (printer, "details-acquired", TRUE);
@@ -4222,6 +4259,26 @@ static const struct {
 };
 
 static const struct {
+  const char *ipp_option_name;
+  const char *gtk_option_name;
+  const char *translation;
+} ipp_option_translations[] = {
+  { "sides", "gtk-duplex", N_("Two Sided") },
+};
+
+static const struct {
+  const char *ipp_option_name;
+  const char *ipp_choice;
+  const char *translation;
+} ipp_choice_translations[] = {
+  { "sides", "one-sided", NC_("sides", "One Sided") },
+  /* Translators: this is an option of "Two Sided" */
+  { "sides", "two-sided-long-edge", NC_("sides", "Long Edge (Standard)") },
+  /* Translators: this is an option of "Two Sided" */
+  { "sides", "two-sided-short-edge", NC_("sides", "Short Edge (Flip)") },
+};
+
+static const struct {
   const char *lpoption;
   const char *name;
 } lpoption_names[] = {
@@ -4914,6 +4971,144 @@ colord_printer_option_set_changed_cb (GtkPrinterOptionSet *set,
 }
 #endif
 
+/*
+ * Lookup translation and Gtk+ name of given IPP option name.
+ */
+static gboolean
+get_ipp_option_translation (const gchar  *ipp_option_name,
+                            gchar       **gtk_option_name,
+                            gchar       **translation)
+{
+  gint i;
+
+  *gtk_option_name = NULL;
+  *translation = NULL;
+
+  for (i = 0; i < G_N_ELEMENTS (ipp_option_translations); i++)
+    {
+      if (g_strcmp0 (ipp_option_translations[i].ipp_option_name, ipp_option_name) == 0)
+        {
+          *gtk_option_name = g_strdup (ipp_option_translations[i].gtk_option_name);
+          *translation = g_strdup (_(ipp_option_translations[i].translation));
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+/*
+ * Lookup translation of given IPP choice.
+ */
+static gchar *
+get_ipp_choice_translation (const gchar  *ipp_option_name,
+                            const gchar  *ipp_choice)
+{
+  gchar *translation = NULL;
+  gint   i;
+
+  for (i = 0; i < G_N_ELEMENTS (ipp_choice_translations); i++)
+    {
+      if (g_strcmp0 (ipp_choice_translations[i].ipp_option_name, ipp_option_name) == 0 &&
+          g_strcmp0 (ipp_choice_translations[i].ipp_choice, ipp_choice) == 0)
+        {
+          translation = g_strdup (g_dpgettext2 (GETTEXT_PACKAGE,
+                                                ipp_option_name,
+                                                ipp_choice_translations[i].translation));
+          break;
+        }
+    }
+
+  return translation;
+}
+
+/*
+ * Look the IPP option up in given set of options.
+ * Create it if it doesn't exist and set its default value
+ * if available.
+ */
+static GtkPrinterOption *
+setup_ipp_option (gchar               *ipp_option_name,
+                  gchar               *ipp_choice_default,
+                  GList               *ipp_choices,
+                  GtkPrinterOptionSet *set)
+{
+  GtkPrinterOption *option = NULL;
+  gchar            *gtk_option_name = NULL;
+  gchar            *translation = NULL;
+  gchar            *ipp_choice;
+  gsize             i;
+
+  get_ipp_option_translation (ipp_option_name,
+                              &gtk_option_name,
+                              &translation);
+
+  /* Look the option up in the given set of options. */
+  if (gtk_option_name != NULL)
+    option = gtk_printer_option_set_lookup (set, gtk_option_name);
+
+  /* The option was not found, create it from given choices. */
+  if (option == NULL &&
+      ipp_choices != NULL)
+    {
+      GList  *iter;
+      gsize   length;
+      char  **choices = NULL;
+      char  **choices_display = NULL;
+
+      option = gtk_printer_option_new (gtk_option_name,
+                                       translation,
+                                       GTK_PRINTER_OPTION_TYPE_PICKONE);
+
+      length = g_list_length (ipp_choices);
+
+      choices = g_new0 (char *, length);
+      choices_display = g_new0 (char *, length);
+
+      i = 0;
+      for (iter = ipp_choices; iter != NULL; iter = iter->next)
+        {
+          ipp_choice = (gchar *) iter->data;
+
+          choices[i] = g_strdup (ipp_choice);
+
+          translation = get_ipp_choice_translation (ipp_option_name,
+                                                    ipp_choice);
+          if (translation != NULL)
+            choices_display[i] = translation;
+          else
+            choices_display[i] = g_strdup (ipp_choice);
+
+          i++;
+        }
+
+      if (choices != NULL &&
+          choices_display != NULL)
+        {
+          gtk_printer_option_choices_from_array (option,
+                                                 length,
+                                                 choices,
+                                                 choices_display);
+        }
+
+      option_set_is_ipp_option (option, TRUE);
+
+      gtk_printer_option_set_add (set, option);
+
+      g_free (choices);
+      g_free (choices_display);
+    }
+
+  /* The option exists. Set its default value if available. */
+  if (option != NULL &&
+      ipp_choice_default != NULL)
+    {
+      gtk_printer_option_set (option, ipp_choice_default);
+    }
+
+  return option;
+}
+
 static GtkPrinterOptionSet *
 cups_printer_get_options (GtkPrinter           *printer,
                          GtkPrintSettings     *settings,
@@ -5154,6 +5349,18 @@ cups_printer_get_options (GtkPrinter           *printer,
       for (i = 0; i < ppd_file->num_groups; i++)
         handle_group (set, ppd_file, &ppd_file->groups[i], &ppd_file->groups[i], settings);
     }
+  else
+    {
+      /* Try IPP options */
+
+      option = setup_ipp_option ("sides",
+                                 cups_printer->sides_default,
+                                 cups_printer->sides_supported,
+                                 set);
+
+      if (option != NULL)
+        set_option_from_settings (option, settings);
+    }
 
   /* Now honor the user set defaults for this printer */
   num_opts = cups_get_user_options (gtk_printer_get_name (printer), 0, &opts);
@@ -5207,10 +5414,17 @@ cups_printer_get_options (GtkPrinter           *printer,
           option = gtk_printer_option_set_lookup (set, "gtk-duplex");
           if (option && opts[i].value)
             {
-              if (strcmp (opts[i].value, "two-sided-short-edge") == 0)
-                gtk_printer_option_set (option, "DuplexTumble");
-              else if (strcmp (opts[i].value, "two-sided-long-edge") == 0)
-                gtk_printer_option_set (option, "DuplexNoTumble");
+              if (!option_is_ipp_option (option))
+                {
+                  if (strcmp (opts[i].value, "two-sided-short-edge") == 0)
+                    gtk_printer_option_set (option, "DuplexTumble");
+                  else if (strcmp (opts[i].value, "two-sided-long-edge") == 0)
+                    gtk_printer_option_set (option, "DuplexNoTumble");
+                }
+              else
+                {
+                  gtk_printer_option_set (option, opts[i].value);
+                }
             }
         }
       else
@@ -5376,11 +5590,13 @@ map_settings_to_option (GtkPrinterOption  *option,
                        gint               n_elements,
                        GtkPrintSettings  *settings,
                        const gchar       *standard_name,
-                       const gchar       *cups_name)
+                       const gchar       *cups_name,
+                       const gchar       *ipp_name)
 {
   int i;
   char *name;
   const char *cups_value;
+  const char *ipp_value;
   const char *standard_value;
 
   /* If the cups-specific setting is set, always use that */
@@ -5394,6 +5610,17 @@ map_settings_to_option (GtkPrinterOption  *option,
       return;
     }
 
+  /* If the IPP-specific setting is set, use that */
+  name = g_strdup_printf ("cups-%s", ipp_name);
+  ipp_value = gtk_print_settings_get (settings, name);
+  g_free (name);
+
+  if (ipp_value != NULL)
+    {
+      gtk_printer_option_set (option, ipp_value);
+      return;
+    }
+
   /* Otherwise we try to convert from the general setting */
   standard_value = gtk_print_settings_get (settings, standard_name);
   if (standard_value == NULL)
@@ -5426,7 +5653,9 @@ map_option_to_settings (const gchar       *value,
                        gint               n_elements,
                        GtkPrintSettings  *settings,
                        const gchar       *standard_name,
-                       const gchar       *cups_name)
+                       const gchar       *cups_name,
+                       const gchar       *ipp_name,
+                       gboolean           is_ipp_option)
 {
   int i;
   char *name;
@@ -5460,8 +5689,13 @@ map_option_to_settings (const gchar       *value,
     }
 
   /* Always set the corresponding cups-specific setting */
-  name = g_strdup_printf ("cups-%s", cups_name);
+  if (is_ipp_option)
+    name = g_strdup_printf ("cups-%s", ipp_name);
+  else
+    name = g_strdup_printf ("cups-%s", cups_name);
+
   gtk_print_settings_set (settings, name, value);
+
   g_free (name);
 }
 
@@ -5522,16 +5756,20 @@ set_option_from_settings (GtkPrinterOption *option,
 
   if (strcmp (option->name, "gtk-paper-source") == 0)
     map_settings_to_option (option, paper_source_map, G_N_ELEMENTS (paper_source_map),
-                            settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE, "InputSlot");
+                            settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE,
+                            "InputSlot", NULL);
   else if (strcmp (option->name, "gtk-output-tray") == 0)
     map_settings_to_option (option, output_tray_map, G_N_ELEMENTS (output_tray_map),
-                           settings, GTK_PRINT_SETTINGS_OUTPUT_BIN, "OutputBin");
+                           settings, GTK_PRINT_SETTINGS_OUTPUT_BIN,
+                           "OutputBin", NULL);
   else if (strcmp (option->name, "gtk-duplex") == 0)
     map_settings_to_option (option, duplex_map, G_N_ELEMENTS (duplex_map),
-                           settings, GTK_PRINT_SETTINGS_DUPLEX, "Duplex");
+                           settings, GTK_PRINT_SETTINGS_DUPLEX,
+                           "Duplex", "sides");
   else if (strcmp (option->name, "cups-OutputMode") == 0)
     map_settings_to_option (option, output_mode_map, G_N_ELEMENTS (output_mode_map),
-                           settings, GTK_PRINT_SETTINGS_QUALITY, "OutputMode");
+                           settings, GTK_PRINT_SETTINGS_QUALITY,
+                           "OutputMode", NULL);
   else if (strcmp (option->name, "cups-Resolution") == 0)
     {
       cups_value = gtk_print_settings_get (settings, option->name);
@@ -5565,16 +5803,19 @@ set_option_from_settings (GtkPrinterOption *option,
     }
   else if (strcmp (option->name, "gtk-paper-type") == 0)
     map_settings_to_option (option, media_type_map, G_N_ELEMENTS (media_type_map),
-                           settings, GTK_PRINT_SETTINGS_MEDIA_TYPE, "MediaType");
+                           settings, GTK_PRINT_SETTINGS_MEDIA_TYPE,
+                           "MediaType", NULL);
   else if (strcmp (option->name, "gtk-n-up") == 0)
     {
       map_settings_to_option (option, all_map, G_N_ELEMENTS (all_map),
-                             settings, GTK_PRINT_SETTINGS_NUMBER_UP, "number-up");
+                             settings, GTK_PRINT_SETTINGS_NUMBER_UP,
+                             "number-up", NULL);
     }
   else if (strcmp (option->name, "gtk-n-up-layout") == 0)
     {
       map_settings_to_option (option, all_map, G_N_ELEMENTS (all_map),
-                             settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, "number-up-layout");
+                             settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT,
+                             "number-up-layout", NULL);
     }
   else if (strcmp (option->name, "gtk-billing-info") == 0)
     {
@@ -5632,16 +5873,20 @@ foreach_option_get_settings (GtkPrinterOption *option,
 
   if (strcmp (option->name, "gtk-paper-source") == 0)
     map_option_to_settings (value, paper_source_map, G_N_ELEMENTS (paper_source_map),
-                           settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE, "InputSlot");
+                           settings, GTK_PRINT_SETTINGS_DEFAULT_SOURCE,
+                           "InputSlot", NULL, FALSE);
   else if (strcmp (option->name, "gtk-output-tray") == 0)
     map_option_to_settings (value, output_tray_map, G_N_ELEMENTS (output_tray_map),
-                           settings, GTK_PRINT_SETTINGS_OUTPUT_BIN, "OutputBin");
+                           settings, GTK_PRINT_SETTINGS_OUTPUT_BIN,
+                           "OutputBin", NULL, FALSE);
   else if (strcmp (option->name, "gtk-duplex") == 0)
     map_option_to_settings (value, duplex_map, G_N_ELEMENTS (duplex_map),
-                           settings, GTK_PRINT_SETTINGS_DUPLEX, "Duplex");
+                           settings, GTK_PRINT_SETTINGS_DUPLEX,
+                           "Duplex", "sides", option_is_ipp_option (option));
   else if (strcmp (option->name, "cups-OutputMode") == 0)
     map_option_to_settings (value, output_mode_map, G_N_ELEMENTS (output_mode_map),
-                           settings, GTK_PRINT_SETTINGS_QUALITY, "OutputMode");
+                           settings, GTK_PRINT_SETTINGS_QUALITY,
+                           "OutputMode", NULL, FALSE);
   else if (strcmp (option->name, "cups-Resolution") == 0)
     {
       int res, res_x, res_y;
@@ -5661,13 +5906,16 @@ foreach_option_get_settings (GtkPrinterOption *option,
     }
   else if (strcmp (option->name, "gtk-paper-type") == 0)
     map_option_to_settings (value, media_type_map, G_N_ELEMENTS (media_type_map),
-                           settings, GTK_PRINT_SETTINGS_MEDIA_TYPE, "MediaType");
+                           settings, GTK_PRINT_SETTINGS_MEDIA_TYPE,
+                           "MediaType", NULL, FALSE);
   else if (strcmp (option->name, "gtk-n-up") == 0)
     map_option_to_settings (value, all_map, G_N_ELEMENTS (all_map),
-                           settings, GTK_PRINT_SETTINGS_NUMBER_UP, "number-up");
+                           settings, GTK_PRINT_SETTINGS_NUMBER_UP,
+                           "number-up", NULL, FALSE);
   else if (strcmp (option->name, "gtk-n-up-layout") == 0)
     map_option_to_settings (value, all_map, G_N_ELEMENTS (all_map),
-                           settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, "number-up-layout");
+                           settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT,
+                           "number-up-layout", NULL, FALSE);
   else if (strcmp (option->name, "gtk-billing-info") == 0 && strlen (value) > 0)
     gtk_print_settings_set (settings, "cups-job-billing", value);
   else if (strcmp (option->name, "gtk-job-prio") == 0)
diff --git a/modules/printbackends/cups/gtkprintercups.c b/modules/printbackends/cups/gtkprintercups.c
index 7fd828e..1e7188e 100644
--- a/modules/printbackends/cups/gtkprintercups.c
+++ b/modules/printbackends/cups/gtkprintercups.c
@@ -133,6 +133,8 @@ gtk_printer_cups_init (GtkPrinterCups *printer)
   printer->media_left_margin_default = 0;
   printer->media_right_margin_default = 0;
   printer->media_margin_default_set = FALSE;
+  printer->sides_default = NULL;
+  printer->sides_supported = NULL;
 }
 
 static void
@@ -181,6 +183,9 @@ gtk_printer_cups_finalize (GObject *object)
   g_list_free_full (printer->media_supported, g_free);
   g_list_free_full (printer->media_size_supported, g_free);
 
+  g_free (printer->sides_default);
+  g_list_free_full (printer->sides_supported, g_free);
+
   if (printer->get_remote_ppd_poll > 0)
     g_source_remove (printer->get_remote_ppd_poll);
   printer->get_remote_ppd_attempts = 0;
diff --git a/modules/printbackends/cups/gtkprintercups.h b/modules/printbackends/cups/gtkprintercups.h
index aeded4f..170a4a2 100644
--- a/modules/printbackends/cups/gtkprintercups.h
+++ b/modules/printbackends/cups/gtkprintercups.h
@@ -66,6 +66,8 @@ struct _GtkPrinterCups
   gint      media_left_margin_default;
   gint      media_right_margin_default;
   gboolean  media_margin_default_set;
+  gchar    *sides_default;
+  GList    *sides_supported;
 
   gchar  *default_cover_before;
   gchar  *default_cover_after;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]