[gtk/matthiasc/for-master: 5/8] printeroptionwidget: Port to GtkDropDown



commit c3b43f2ad216479c900c0b7cfd56e8de680f54c0
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Jun 11 19:59:35 2020 -0400

    printeroptionwidget: Port to GtkDropDown
    
    Use GtkDropDown instead of GtkComboBox in the print dialog.

 gtk/gtkprinteroptionwidget.c | 433 +++++++++++++++++++++++++++++++------------
 1 file changed, 311 insertions(+), 122 deletions(-)
---
diff --git a/gtk/gtkprinteroptionwidget.c b/gtk/gtkprinteroptionwidget.c
index a63d614806..b83040f404 100644
--- a/gtk/gtkprinteroptionwidget.c
+++ b/gtk/gtkprinteroptionwidget.c
@@ -23,9 +23,10 @@
 
 #include "gtkintl.h"
 #include "gtkcheckbutton.h"
-#include "gtkcelllayout.h"
-#include "gtkcellrenderertext.h"
-#include "gtkcombobox.h"
+#include "gtkdropdown.h"
+#include "gtklistitem.h"
+#include "gtksignallistitemfactory.h"
+#include "gtkentry.h"
 #include "gtkfilechooserdialog.h"
 #include "gtkimage.h"
 #include "gtklabel.h"
@@ -263,168 +264,357 @@ gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *widget,
   g_object_notify (G_OBJECT (widget), "source");
 }
 
+#define GTK_TYPE_STRING_PAIR (gtk_string_pair_get_type ())
+G_DECLARE_FINAL_TYPE (GtkStringPair, gtk_string_pair, GTK, STRING_PAIR, GObject)
+
+struct _GtkStringPair {
+  GObject parent_instance;
+  char *id;
+  char *string;
+};
+
 enum {
-  NAME_COLUMN,
-  VALUE_COLUMN,
-  N_COLUMNS
+  PROP_ID = 1,
+  PROP_STRING,
+  PROP_NUM_PROPERTIES
 };
 
+G_DEFINE_TYPE (GtkStringPair, gtk_string_pair, G_TYPE_OBJECT);
+
+static void
+gtk_string_pair_init (GtkStringPair *pair)
+{
+}
+
+static void
+gtk_string_pair_finalize (GObject *object)
+{
+  GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+  g_free (pair->id);
+  g_free (pair->string);
+
+  G_OBJECT_CLASS (gtk_string_pair_parent_class)->finalize (object);
+}
+
+static void
+gtk_string_pair_set_property (GObject      *object,
+                              guint         property_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+  GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+  switch (property_id)
+    {
+    case PROP_STRING:
+      g_free (pair->string);
+      pair->string = g_value_dup_string (value);
+      break;
+
+    case PROP_ID:
+      g_free (pair->id);
+      pair->id = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_string_pair_get_property (GObject      *object,
+                              guint         property_id,
+                              GValue       *value,
+                              GParamSpec   *pspec)
+{
+  GtkStringPair *pair = GTK_STRING_PAIR (object);
+
+  switch (property_id)
+    {
+    case PROP_STRING:
+      g_value_set_string (value, pair->string);
+      break;
+
+    case PROP_ID:
+      g_value_set_string (value, pair->id);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_string_pair_class_init (GtkStringPairClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GParamSpec *pspec;
+
+  object_class->finalize = gtk_string_pair_finalize;
+  object_class->set_property = gtk_string_pair_set_property;
+  object_class->get_property = gtk_string_pair_get_property;
+
+  pspec = g_param_spec_string ("string", "String", "String",
+                               NULL,
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_property (object_class, PROP_STRING, pspec);
+
+  pspec = g_param_spec_string ("id", "ID", "ID",
+                               NULL,
+                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_property (object_class, PROP_ID, pspec);
+}
+
+static GtkStringPair *
+gtk_string_pair_new (const char *id,
+                     const char *string)
+{
+  return g_object_new (GTK_TYPE_STRING_PAIR,
+                       "id", id,
+                       "string", string,
+                       NULL);
+}
+
+static const char *
+gtk_string_pair_get_string (GtkStringPair *pair)
+{
+  return pair->string;
+}
+
+static const char *
+gtk_string_pair_get_id (GtkStringPair *pair)
+{
+  return pair->id;
+}
+
 static void
 combo_box_set_model (GtkWidget *combo_box)
 {
-  GtkListStore *store;
+  GListStore *store;
 
-  store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
-  gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store));
+  store = g_list_store_new (GTK_TYPE_STRING_PAIR);
+  gtk_drop_down_set_model (GTK_DROP_DOWN (combo_box), G_LIST_MODEL (store));
   g_object_unref (store);
 }
 
+static void
+setup_no_item (GtkSignalListItemFactory *factory,
+               GtkListItem              *item)
+{
+}
+
+static void
+setup_list_item (GtkSignalListItemFactory *factory,
+                 GtkListItem              *item)
+{
+  GtkWidget *label;
+
+  label = gtk_label_new ("");
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_list_item_set_child (item, label);
+}
+
+static void
+bind_list_item (GtkSignalListItemFactory *factory,
+                GtkListItem              *item)
+{
+  GtkStringPair *pair;
+  GtkWidget *label;
+
+  pair = gtk_list_item_get_item (item);
+  label = gtk_list_item_get_child (item);
+
+  gtk_label_set_text (GTK_LABEL (label), gtk_string_pair_get_string (pair));
+}
+
 static void
 combo_box_set_view (GtkWidget *combo_box)
 {
-  GtkCellRenderer *cell;
+  GtkListItemFactory *factory;
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (combo_box), factory);
+  g_object_unref (factory);
+}
+
+static void
+selected_changed (GtkDropDown *dropdown,
+                  GParamSpec *pspec,
+                  gpointer data)
+{
+  GListModel *model;
+  guint selected;
+  GtkStringPair *pair;
+  GtkWidget *entry = data;
+
+  model = gtk_drop_down_get_model (dropdown);
+  selected = gtk_drop_down_get_selected (dropdown);
+
+  pair = g_list_model_get_item (model, selected);
+  if (pair)
+    {
+      gtk_editable_set_text (GTK_EDITABLE (entry), gtk_string_pair_get_string (pair));
+      g_object_unref (pair);
+    }
+  else
+    gtk_editable_set_text (GTK_EDITABLE (entry), "");
 
-  cell = gtk_cell_renderer_text_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE);
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell,
-                                  "text", NAME_COLUMN,
-                                   NULL);
 }
 
 static GtkWidget *
 combo_box_entry_new (void)
 {
-  GtkWidget *combo_box;
-  combo_box = g_object_new (GTK_TYPE_COMBO_BOX, "has-entry", TRUE, NULL);
+  GtkWidget *hbox, *entry, *button;
+  GtkListItemFactory *factory;
 
-  combo_box_set_model (combo_box);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_add_css_class (hbox, "linked");
 
-  gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (combo_box), NAME_COLUMN);
+  entry = gtk_entry_new ();
+  button = gtk_drop_down_new ();
+  combo_box_set_model (button);
 
-  return combo_box;
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_no_item), NULL);
+  gtk_drop_down_set_factory (GTK_DROP_DOWN (button), factory);
+  g_object_unref (factory);
+
+  factory = gtk_signal_list_item_factory_new ();
+  g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL);
+  g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL);
+  gtk_drop_down_set_list_factory (GTK_DROP_DOWN (button), factory);
+  g_object_unref (factory);
+
+  g_signal_connect (button, "notify::selected", G_CALLBACK (selected_changed), entry);
+
+  gtk_box_append (GTK_BOX (hbox), entry);
+  gtk_box_append (GTK_BOX (hbox), button);
+
+  return hbox;
 }
 
 static GtkWidget *
 combo_box_new (void)
 {
   GtkWidget *combo_box;
-  combo_box = gtk_combo_box_new ();
+
+  combo_box = gtk_drop_down_new ();
 
   combo_box_set_model (combo_box);
   combo_box_set_view (combo_box);
 
   return combo_box;
 }
-  
+
 static void
 combo_box_append (GtkWidget   *combo,
-                 const gchar *display_text,
-                 const gchar *value)
+                  const gchar *display_text,
+                  const gchar *value)
 {
-  GtkTreeModel *model;
-  GtkListStore *store;
-  GtkTreeIter iter;
-  
-  model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
-  store = GTK_LIST_STORE (model);
-
-  gtk_list_store_append (store, &iter);
-  gtk_list_store_set (store, &iter,
-                     NAME_COLUMN, display_text,
-                     VALUE_COLUMN, value,
-                     -1);
-}
+  GtkWidget *dropdown;
+  GListModel *model;
+  GtkStringPair *object;
 
-struct ComboSet {
-  GtkComboBox *combo;
-  const gchar *value;
-};
+  if (GTK_IS_DROP_DOWN (combo))
+    dropdown = combo;
+  else
+    dropdown = gtk_widget_get_last_child (combo);
 
-static gboolean
-set_cb (GtkTreeModel *model, 
-       GtkTreePath  *path, 
-       GtkTreeIter  *iter, 
-       gpointer      data)
-{
-  struct ComboSet *set_data = data;
-  gboolean found;
-  char *value;
-  
-  gtk_tree_model_get (model, iter, VALUE_COLUMN, &value, -1);
-  found = (strcmp (value, set_data->value) == 0);
-  g_free (value);
-  
-  if (found)
-    gtk_combo_box_set_active_iter (set_data->combo, iter);
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
 
-  return found;
+  object = gtk_string_pair_new (value, display_text);
+  g_list_store_append (G_LIST_STORE (model), object);
+  g_object_unref (object);
 }
 
 static void
 combo_box_set (GtkWidget   *combo,
-              const gchar *value)
+               const gchar *value)
 {
-  GtkTreeModel *model;
-  struct ComboSet set_data;
-  
-  model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+  GtkWidget *dropdown;
+  GListModel *model;
+  guint i;
+
+  if (GTK_IS_DROP_DOWN (combo))
+    dropdown = combo;
+  else
+    dropdown = gtk_widget_get_last_child (combo);
 
-  set_data.combo = GTK_COMBO_BOX (combo);
-  set_data.value = value;
-  gtk_tree_model_foreach (model, set_cb, &set_data);
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+
+  for (i = 0; i < g_list_model_get_n_items (model); i++)
+    {
+      GtkStringPair *item = g_list_model_get_item (model, i);
+      if (strcmp (value, gtk_string_pair_get_id (item)) == 0)
+        {
+          gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i);
+          g_object_unref (item);
+          break;
+        }
+      g_object_unref (item);
+    }
 }
 
 static gchar *
 combo_box_get (GtkWidget *combo, gboolean *custom)
 {
-  GtkTreeModel *model;
-  gchar *value;
-  GtkTreeIter iter;
+  GtkWidget *dropdown;
+  GListModel *model;
+  guint selected;
+  gpointer item;
+  const char *id;
+  const char *string;
+
+  if (GTK_IS_DROP_DOWN (combo))
+    dropdown = combo;
+  else
+    dropdown = gtk_widget_get_last_child (combo);
 
-  model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+  model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown));
+  selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown));
+  item = g_list_model_get_item (model, selected);
+  if (item)
+    {
+      id = gtk_string_pair_get_id (item);
+      string = gtk_string_pair_get_string (item);
+      g_object_unref (item);
+    }
+  else
+    {
+      id = "";
+      string = NULL;
+    }
 
-  value = NULL;
-  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter))
+  if (dropdown == combo) // no entry
     {
-      gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1);
       *custom = FALSE;
+      return g_strdup (id);
     }
   else
     {
-      if (gtk_combo_box_get_has_entry (GTK_COMBO_BOX (combo)))
+      const char *text;
+
+      text = gtk_editable_get_text (GTK_EDITABLE (gtk_widget_get_first_child (combo)));
+      if (g_strcmp0 (text, string) == 0)
         {
-          value = g_strdup (gtk_editable_get_text (GTK_EDITABLE (gtk_combo_box_get_child (GTK_COMBO_BOX 
(combo)))));
-          *custom = TRUE;
+          *custom = FALSE;
+          return g_strdup (id);
         }
-
-      if (!value || !gtk_tree_model_get_iter_first (model, &iter))
-        return value;
-
-      /* If the user entered an item from the dropdown list manually, return
-       * the non-custom option instead. */
-      do
+      else
         {
-          gchar *val, *name;
-          gtk_tree_model_get (model, &iter, VALUE_COLUMN, &val,
-                                            NAME_COLUMN, &name, -1);
-          if (g_str_equal (value, name))
-            {
-              *custom = FALSE;
-              g_free (name);
-              g_free (value);
-              return val;
-            }
-
-          g_free (val);
-          g_free (name);
+          *custom = TRUE;
+          return g_strdup (text);
         }
-      while (gtk_tree_model_iter_next (model, &iter));
     }
-
-  return value;
 }
 
-
 static void
 deconstruct_widgets (GtkPrinterOptionWidget *widget)
 {
@@ -594,6 +784,7 @@ filter_numeric (const gchar *val,
 
 static void
 combo_changed_cb (GtkWidget              *combo,
+                  GParamSpec             *pspec,
                  GtkPrinterOptionWidget *widget)
 {
   GtkPrinterOptionWidgetPrivate *priv = widget->priv;
@@ -604,7 +795,7 @@ combo_changed_cb (GtkWidget              *combo,
 
   g_signal_handler_block (priv->source, priv->source_changed_handler);
   
-  value = combo_box_get (combo, &custom);
+  value = combo_box_get (priv->combo, &custom);
 
   /* Handle constraints if the user entered a custom value. */
   if (custom)
@@ -639,12 +830,9 @@ combo_changed_cb (GtkWidget              *combo,
 
       if (changed)
         {
-          GtkEntry *entry;
-         
-         entry = GTK_ENTRY (gtk_combo_box_get_child (GTK_COMBO_BOX (combo)));
-
+          GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
           gtk_editable_set_text (GTK_EDITABLE (entry), filtered_val);
-       }
+        }
       value = filtered_val;
     }
 
@@ -746,9 +934,12 @@ construct_widgets (GtkPrinterOptionWidget *widget)
 
   if (source == NULL)
     {
-      priv->combo = combo_box_new ();
-      combo_box_append (priv->combo,_("Not available"), "None");
-      gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo), 0);
+      const char * strings[2];
+      strings[0] = _("Not available");
+      strings[1] = NULL;
+      priv->combo = gtk_drop_down_new ();
+      gtk_drop_down_set_from_strings (GTK_DROP_DOWN (priv->combo), strings);
+      gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0);
       gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE);
       gtk_widget_show (priv->combo);
       gtk_box_append (GTK_BOX (widget), priv->combo);
@@ -770,20 +961,17 @@ construct_widgets (GtkPrinterOptionWidget *widget)
       if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE)
         {
           priv->combo = combo_box_new ();
-       }
+        }
       else
         {
           priv->combo = combo_box_entry_new ();
 
           if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD ||
-             source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE)
-           {
-              GtkEntry *entry;
-
-             entry = GTK_ENTRY (gtk_combo_box_get_child (GTK_COMBO_BOX (priv->combo)));
-
-              gtk_entry_set_visibility (entry, FALSE); 
-           }
+              source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE)
+            {
+              GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
+              gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
+            }
         }
 
       for (i = 0; i < source->num_choices; i++)
@@ -792,7 +980,10 @@ construct_widgets (GtkPrinterOptionWidget *widget)
                           source->choices[i]);
       gtk_widget_show (priv->combo);
       gtk_box_append (GTK_BOX (widget), priv->combo);
-      g_signal_connect (priv->combo, "changed", G_CALLBACK (combo_changed_cb), widget);
+      if (GTK_IS_DROP_DOWN (priv->combo))
+        g_signal_connect (priv->combo, "notify::selected", G_CALLBACK (combo_changed_cb),widget);
+      else
+        g_signal_connect (gtk_widget_get_last_child (priv->combo), "notify::selected",G_CALLBACK 
(combo_changed_cb), widget);
 
       text = g_strdup_printf ("%s:", source->display_text);
       priv->label = gtk_label_new_with_mnemonic (text);
@@ -951,9 +1142,7 @@ update_widgets (GtkPrinterOptionWidget *widget)
     case GTK_PRINTER_OPTION_TYPE_PICKONE_INT:
     case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING:
       {
-        GtkEntry *entry;
-
-        entry = GTK_ENTRY (gtk_combo_box_get_child (GTK_COMBO_BOX (priv->combo)));
+        GtkWidget *entry = gtk_widget_get_first_child (priv->combo);
         if (gtk_printer_option_has_choice (source, source->value))
           combo_box_set (priv->combo, source->value);
         else


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