[gimp/gimp-attributes-wip] libgimpbase: GimpAttributes sorting; Plug-ins: attributes fixed for new sorting. Since GHashTable do



commit 584e141ea661cc85c3dfd0d835ecff3c5efc3887
Author: Hartmut Kuhse <hk_priv gmx de>
Date:   Mon Oct 6 17:43:45 2014 +0200

    libgimpbase: GimpAttributes sorting; Plug-ins: attributes fixed for new sorting.
    Since GHashTable does not sort keys, a GList was necessary for sorting purposes.
    But plain string sorting is not enough for structured tags, when I got an image
    with 176(!) xmpMM.History elements. In string sorting, after 10 comes 100, so an
    enhanced sorting was necessary.

 libgimpbase/gimpattribute.c       |  111 +++++++++++++++++++++++---
 libgimpbase/gimpattribute.h       |    1 +
 libgimpbase/gimpattributes.c      |  159 ++++++++++++++++++++++++++++++++++---
 libgimpbase/gimpattributes.h      |    5 +
 libgimpbase/gimpbase.def          |    3 +
 plug-ins/common/attributes.c      |   42 ++++++----
 plug-ins/ui/plug-in-attributes.ui |   71 +++++++++++++---
 7 files changed, 337 insertions(+), 55 deletions(-)
---
diff --git a/libgimpbase/gimpattribute.c b/libgimpbase/gimpattribute.c
index c1645d0..c8169ac 100644
--- a/libgimpbase/gimpattribute.c
+++ b/libgimpbase/gimpattribute.c
@@ -73,6 +73,7 @@ struct _GimpAttributeClass {
 
 struct _GimpAttributePrivate {
   gchar                      *name;
+  gchar                      *sorted_name;
 
   gchar                      *tag_value;
   gchar                      *interpreted_value;
@@ -90,7 +91,6 @@ struct _GimpAttributePrivate {
   gboolean                    has_structure;
   GimpAttributeStructureType  structure_type;
   GSList                     *attribute_structure;
-
 };
 
 enum  {
@@ -165,6 +165,10 @@ static gboolean                get_tag_date                          (gchar
 static gchar *                 gimp_attribute_escape_value           (gchar               *name,
                                                                       gchar               *value,
                                                                       gboolean            *encoded);
+static gchar *                 gimp_attribute_get_structure_number   (gchar               *cptag,
+                                                                      gint                 start,
+                                                                      gint                *struct_number);
+
 static gchar*                  string_replace_str                    (const gchar         *original,
                                                                       const gchar         *old_pattern,
                                                                       const gchar         *replacement);
@@ -232,6 +236,31 @@ gimp_attribute_get_name (GimpAttribute* attribute)
 }
 
 /**
+ * gimp_attribute_get_sortable_name:
+ *
+ * @attribute:    a @GimpAttribute
+ *
+ * Return value: name of the #GimpAttribute object for sorting
+ * e.g. from tag:
+ *  "xmp.xmpMM.History[2]..."
+ * it returns:
+ *  "xmp.xmpMM.History[000002]..."
+ *
+ * Since: 2.10
+ */
+const gchar*
+gimp_attribute_get_sortable_name (GimpAttribute* attribute)
+{
+  GimpAttributePrivate *private;
+  g_return_val_if_fail (attribute != NULL, NULL);
+  private = GIMP_ATTRIBUTE_GET_PRIVATE (attribute);
+  if (private->sorted_name)
+    return (const gchar *) private->sorted_name;
+  else
+    return (const gchar *) private->name;
+}
+
+/**
  * gimp_attribute_get_attribute_type:
  *
  * @attribute:    a @GimpAttribute
@@ -1066,30 +1095,40 @@ gimp_attribute_set_name (GimpAttribute* attribute, const gchar* value)
   else if (!g_strcmp0 (lowchar, "xmp"))
     {
       gint     j;
-      gint     p1 = 0;
-      gint     p2 = 0;
-      gboolean is_known = FALSE;
+      gint     p1                 = 0;
+      gint     p2                 = 0;
+      gboolean is_known           = FALSE;
+      gchar   *structure_tag_name = NULL;
+
+      structure_tag_name = g_strdup (private->name);
+
       private->tag_type = TAG_XMP;
 
       while (p2 != -1)
         {
-
-          p2 = string_index_of (private->name, "[", p1);
+          p2 = string_index_of (structure_tag_name, "[", p1);
 
           if (p2 > -1)
             {
               gchar *struct_string = NULL;
+              gint   struct_number;
 
               private->has_structure = TRUE;
-              private->structure_type = STRUCTURE_TYPE_BAG;
+              private->structure_type = STRUCTURE_TYPE_BAG; /* there's no way to get the real type from 
gexiv2 */
 
-              struct_string = string_substring (private->name, 0, p2);
+              struct_string = string_substring (structure_tag_name, 0, p2);
               private->attribute_structure = g_slist_prepend (private->attribute_structure, struct_string);
+              structure_tag_name = gimp_attribute_get_structure_number (structure_tag_name, p2, 
&struct_number);
 
               p1 = p2 + 1;
             }
         }
 
+      if (g_strcmp0 (private->name, structure_tag_name))
+        private->sorted_name = structure_tag_name;
+      else
+        private->sorted_name = NULL;
+
       for (j = 0; j < G_N_ELEMENTS (xmp_namespaces); j++)
         {
           if (! g_strcmp0 (private->attribute_ifd, xmp_namespaces[j]))
@@ -1341,6 +1380,7 @@ gimp_attribute_instance_init (GimpAttribute * attribute)
   private = GIMP_ATTRIBUTE_GET_PRIVATE (attribute);
 
   private->name                    = NULL;
+  private->sorted_name             = NULL;
   private->tag_value               = NULL;
   private->interpreted_value       = NULL;
   private->exif_type               = NULL;
@@ -1375,6 +1415,9 @@ gimp_attribute_finalize (GObject* obj)
   if(private->name)
     _g_free0 (private->name);
 
+  if(private->sorted_name)
+    _g_free0 (private->sorted_name);
+
   if(private->tag_value)
     _g_free0 (private->tag_value);
 
@@ -1425,6 +1468,51 @@ gimp_attribute_set_property (GObject * object,
 {
 }
 
+static gchar *
+gimp_attribute_get_structure_number (gchar *cptag, gint start, gint *number)
+{
+  gint p1;
+  gchar *tag;
+  gchar *new_tag;
+  gchar *oldnr;
+  gchar *newnr;
+
+  start++;
+
+  tag = g_strdup (cptag);
+
+  p1 = string_index_of (tag, "]", start);
+
+  if (p1 > -1)
+    {
+      gchar *number_string = NULL;
+      gint   len;
+
+      len = p1-start;
+
+      number_string = string_substring (tag, start, len);
+
+      *number = atoi (number_string);
+
+      oldnr = g_strdup_printf ("[%d]", *number);
+      newnr = g_strdup_printf ("[%06d]", *number);
+      new_tag = string_replace_str (tag, oldnr, newnr);
+
+      g_free (oldnr);
+      g_free (newnr);
+      g_free (tag);
+      g_free (number_string);
+
+      return new_tag;
+    }
+  else
+    {
+      *number = -1;
+      return NULL;
+    }
+
+}
+
 /**
  * gimp_attribute_get_type
  *
@@ -1481,7 +1569,8 @@ gimp_attribute_get_type (void)
  *
  * Since: 2.10
  */
-static gboolean get_tag_time (gchar *input, TagTime *tm)
+static gboolean
+get_tag_time (gchar *input, TagTime *tm)
 {
   long     val;
   GString *string = NULL;
@@ -1586,7 +1675,8 @@ static gboolean get_tag_time (gchar *input, TagTime *tm)
  *
  * Since: 2.10
  */
-static gboolean get_tag_date (gchar *input, TagDate *dt)
+static gboolean
+get_tag_date (gchar *input, TagDate *dt)
 {
   long     val;
   GString *string = NULL;
@@ -1855,4 +1945,3 @@ string_substring (gchar* string, glong offset, glong len)
   result = g_strndup (((gchar*) string) + offset, (gsize) len);
   return result;
 }
-
diff --git a/libgimpbase/gimpattribute.h b/libgimpbase/gimpattribute.h
index 875036d..adf0951 100644
--- a/libgimpbase/gimpattribute.h
+++ b/libgimpbase/gimpattribute.h
@@ -75,6 +75,7 @@ const gchar*                gimp_attribute_get_attribute_ifd              (GimpA
 const gchar*                gimp_attribute_get_attribute_tag              (GimpAttribute              
*attribute);
 const gboolean              gimp_attribute_is_new_namespace               (GimpAttribute              
*attribute);
 const gchar*                gimp_attribute_get_name                       (GimpAttribute              
*attribute);
+const gchar*                gimp_attribute_get_sortable_name              (GimpAttribute              
*attribute);
 GValue                      gimp_attribute_get_value                      (GimpAttribute              
*attribute);
 gchar*                      gimp_attribute_get_string                     (GimpAttribute              
*attribute);
 GimpAttributeTagType        gimp_attribute_get_tag_type                   (GimpAttribute              
*attribute);
diff --git a/libgimpbase/gimpattributes.c b/libgimpbase/gimpattributes.c
index 7739702..c9ebae8 100644
--- a/libgimpbase/gimpattributes.c
+++ b/libgimpbase/gimpattributes.c
@@ -64,6 +64,7 @@ struct _GimpAttributesClass {
 
 struct _GimpAttributesPrivate {
   GHashTable *attribute_table;
+  GHashTable *sorted_to_attribute;
   GList      *sorted_key_list;
 };
 
@@ -128,6 +129,8 @@ static const gchar*            gimp_attributes_name_to_value               (cons
 
 static gboolean                has_xmp_structure                           (GSList              *xmp_list,
                                                                             const gchar         *entry);
+static GimpAttribute *         gimp_attributes_get_attribute_sorted        (GimpAttributes      *attributes,
+                                                                            const gchar         
*sorted_name);
 
 /**
  * gimp_attributes_new:
@@ -190,6 +193,7 @@ gimp_attributes_instance_init (GimpAttributes * attributes)
 {
   attributes->priv = GIMP_ATTRIBUTES_GET_PRIVATE (attributes);
   attributes->priv->attribute_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
g_object_unref);
+  attributes->priv->sorted_to_attribute = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
   attributes->priv->sorted_key_list = NULL;
 }
 
@@ -206,6 +210,7 @@ gimp_attributes_finalize (GObject* obj)
   attributes = G_TYPE_CHECK_INSTANCE_CAST (obj, GIMP_TYPE_ATTRIBUTES, GimpAttributes);
 
   g_hash_table_unref (attributes->priv->attribute_table);
+  g_hash_table_unref (attributes->priv->sorted_to_attribute);
   g_list_free_full (attributes->priv->sorted_key_list, (GDestroyNotify) g_free);
 
   G_OBJECT_CLASS (gimp_attributes_parent_class)->finalize (obj);
@@ -349,7 +354,7 @@ gimp_attributes_add_attribute (GimpAttributes      *attributes,
                                GimpAttribute       *attribute)
 {
   const gchar *name;
-  const gchar *lowchar;
+  gchar       *lowchar;
 
   g_return_if_fail (GIMP_IS_ATTRIBUTES (attributes));
   g_return_if_fail (GIMP_IS_ATTRIBUTE (attribute));
@@ -363,9 +368,25 @@ gimp_attributes_add_attribute (GimpAttributes      *attributes,
       /* FIXME: really simply add? That means, that an older value is overwritten */
 
       if (g_hash_table_insert (attributes->priv->attribute_table, (gpointer) g_strdup (lowchar), (gpointer) 
attribute))
-        attributes->priv->sorted_key_list = g_list_insert_sorted (attributes->priv->sorted_key_list,
-                                                                  (gpointer) g_strdup (lowchar),
-                                                                  (GCompareFunc) g_strcmp0);
+        {
+          gchar *sortable_tag;
+
+          sortable_tag = g_ascii_strdown (gimp_attribute_get_sortable_name (attribute), -1);
+
+          if (g_hash_table_insert (attributes->priv->sorted_to_attribute, (gpointer) g_strdup 
(sortable_tag), (gpointer) g_strdup (lowchar)))
+            {
+              attributes->priv->sorted_key_list = g_list_insert_sorted (attributes->priv->sorted_key_list,
+                                                                        (gpointer) g_strdup (sortable_tag),
+                                                                        (GCompareFunc) g_strcmp0);
+            }
+          else
+            {
+              g_hash_table_remove (attributes->priv->attribute_table, (gpointer) g_strdup (lowchar));
+            }
+
+          g_free (sortable_tag);
+        }
+      g_free (lowchar);
     }
 }
 
@@ -403,6 +424,49 @@ gimp_attributes_get_attribute (GimpAttributes      *attributes,
 }
 
 /**
+ * gimp_attributes_get_attribute_sorted:
+ *
+ * @attributes: a #GimpAttributes
+ * @name : a #gchar array
+ *
+ * gets the #GimpAttribute object with @sorted_name as
+ * sortable_name
+ * see GimpAttribute::get_sortable_name
+ *
+ * Return value: the #GimpAttribute object if found, NULL otherwise.
+ *
+ * Since : 2.10
+ */
+static GimpAttribute *
+gimp_attributes_get_attribute_sorted (GimpAttributes      *attributes,
+                                      const gchar         *sorted_name)
+{
+  gchar          *lowchar;
+  GimpAttribute  *attribute_data = NULL;
+  gpointer       *data;
+  gchar          *name_of_tag;
+
+  g_return_val_if_fail (GIMP_IS_ATTRIBUTES (attributes), NULL);
+  g_return_val_if_fail (sorted_name != NULL, NULL);
+
+  lowchar = g_ascii_strdown (sorted_name, -1);
+
+  data = g_hash_table_lookup (attributes->priv->sorted_to_attribute, (gpointer) lowchar);
+
+  name_of_tag = (gchar *) data;
+
+  data = g_hash_table_lookup (attributes->priv->attribute_table, (gpointer) name_of_tag);
+  if (data)
+    {
+      attribute_data = (GimpAttribute *) data;
+    }
+
+  g_free (lowchar);
+
+  return attribute_data;
+}
+
+/**
  * gimp_attributes_remove_attribute:
  *
  * @attributes: a #GimpAttributes
@@ -418,15 +482,49 @@ gboolean
 gimp_attributes_remove_attribute (GimpAttributes      *attributes,
                                   const gchar         *name)
 {
-  gchar *lowchar;
-  gboolean success;
+  gchar            *lowchar;
+  gboolean          success = FALSE;
+  GHashTableIter    iter_remove;
+  gpointer          key, value;
+  gchar            *tag_to_remove;
+  gchar            *name_of_tag;
 
   lowchar = g_ascii_strdown (name, -1);
 
-  success = g_hash_table_remove (attributes->priv->attribute_table, (gpointer) lowchar);
+  if (g_hash_table_remove (attributes->priv->attribute_table, (gpointer) lowchar))
+    {
+      gchar *tag_list_remove = NULL;
+
+      g_hash_table_iter_init (&iter_remove, attributes->priv->sorted_to_attribute);
+      while (g_hash_table_iter_next (&iter_remove, &key, &value))
+        {
+          tag_to_remove  = (gchar *) key;
+          name_of_tag    = (gchar *) value;
+
+          if (! g_strcmp0 (lowchar, name_of_tag))
+            break;
+        }
+
+      tag_list_remove = g_strdup (tag_to_remove); /* because removing from hashtable frees tag_to_remove */
+
+      if (g_hash_table_remove (attributes->priv->sorted_to_attribute, (gpointer) tag_to_remove))
+        {
+          attributes->priv->sorted_key_list = g_list_remove (attributes->priv->sorted_key_list,
+                                                             (gconstpointer) tag_list_remove);
+          success = TRUE;
+        }
+      else
+        {
+          if (name_of_tag)
+            g_free (name_of_tag);
+          if (tag_to_remove)
+            g_free (tag_to_remove);
+          success = FALSE;
+        }
+
+      g_free (tag_list_remove);
+    }
 
-  attributes->priv->sorted_key_list = g_list_remove (attributes->priv->sorted_key_list,
-                                                     (gpointer) lowchar);
   g_free (lowchar);
 
   return success;
@@ -528,7 +626,7 @@ gimp_attributes_serialize (GimpAttributes *attributes)
       GimpAttribute  *attribute = NULL;
       gchar          *p_key = (gchar *) key_list->data;
 
-      attribute      = gimp_attributes_get_attribute (attributes, p_key);
+      attribute      = gimp_attributes_get_attribute_sorted (attributes, p_key);
 
       xml = gimp_attribute_get_xml (attribute);
 
@@ -772,7 +870,7 @@ gimp_attributes_print (GimpAttributes *attributes)
       GimpAttribute  *attribute;
       gchar          *p_key = (gchar *) key_list->data;
 
-      attribute      = gimp_attributes_get_attribute (attributes, p_key);
+      attribute      = gimp_attributes_get_attribute_sorted (attributes, p_key);
 
       if (! attribute)
         continue;
@@ -846,7 +944,7 @@ gimp_attributes_to_metadata (GimpAttributes *attributes,
       write_tag      = FALSE;
       namespace      = FALSE;
 
-      attribute      = gimp_attributes_get_attribute (attributes, p_key);
+      attribute      = gimp_attributes_get_attribute_sorted (attributes, p_key);
 
       if (! attribute)
         continue;
@@ -1105,7 +1203,7 @@ gimp_attributes_to_xmp_packet (GimpAttributes *attributes,
       write_tag     = FALSE;
       namespace = FALSE;
 
-      attribute = gimp_attributes_get_attribute (attributes, p_key);
+      attribute = gimp_attributes_get_attribute_sorted (attributes, p_key);
 
       if (! attribute)
         continue;
@@ -1347,6 +1445,41 @@ gimp_attributes_has_tag_type (GimpAttributes       *attributes,
   return FALSE;
 }
 
+GList *
+gimp_attributes_iter_init (GimpAttributes *attributes, GList **iter)
+{
+  g_return_val_if_fail (GIMP_IS_ATTRIBUTES (attributes), NULL);
+
+  *iter = attributes->priv->sorted_key_list;
+
+  return attributes->priv->sorted_key_list;
+}
+
+gboolean
+gimp_attributes_iter_next (GimpAttributes *attributes, GimpAttribute **attribute, GList **prev)
+{
+  gchar         *sorted;
+  GList         *tmp;
+
+  g_return_val_if_fail (GIMP_IS_ATTRIBUTES (attributes), FALSE);
+
+  *attribute = NULL;
+
+  tmp = g_list_next (*prev);
+  if (tmp)
+    {
+      *prev = tmp;
+      sorted = (gchar *) tmp->data;
+
+      *attribute = gimp_attributes_get_attribute_sorted (attributes, sorted);
+    }
+  if (*attribute)
+    return TRUE;
+  else
+    return FALSE;
+
+}
+
 /**
  * gimp_attributes_error_quark:
  *
diff --git a/libgimpbase/gimpattributes.h b/libgimpbase/gimpattributes.h
index 86bbe26..25a9b27 100644
--- a/libgimpbase/gimpattributes.h
+++ b/libgimpbase/gimpattributes.h
@@ -65,6 +65,11 @@ GimpAttributes *                          gimp_attributes_deserialize
 gboolean                                  gimp_attributes_has_tag_type                               
(GimpAttributes      *attributes,
                                                                                                       
GimpAttributeTagType tag_type);
 void                                      gimp_attributes_print                                      
(GimpAttributes      *attributes);
+GList *                                   gimp_attributes_iter_init                                  
(GimpAttributes      *attributes,
+                                                                                                      GList  
            **iter);
+gboolean                                  gimp_attributes_iter_next                                  
(GimpAttributes      *attributes,
+                                                                                                      
GimpAttribute      **attribute,
+                                                                                                      GList  
            **prev);
 
 
 
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
index a4befd3..ac6574e 100644
--- a/libgimpbase/gimpbase.def
+++ b/libgimpbase/gimpbase.def
@@ -8,6 +8,7 @@ EXPORTS
        gimp_attribute_get_attribute_tag
        gimp_attribute_get_interpreted_string
        gimp_attribute_get_name
+       gimp_attribute_get_sortable_name
        gimp_attribute_get_string
        gimp_attribute_get_structure_type
        gimp_attribute_get_tag_type
@@ -30,6 +31,8 @@ EXPORTS
        gimp_attributes_get_resolution
        gimp_attributes_get_table
        gimp_attributes_has_tag_type
+       gimp_attributes_iter_init
+       gimp_attributes_iter_next
        gimp_attributes_new
        gimp_attributes_new_attribute
        gimp_attributes_print
diff --git a/plug-ins/common/attributes.c b/plug-ins/common/attributes.c
index 09b9126..3ca87f6 100644
--- a/plug-ins/common/attributes.c
+++ b/plug-ins/common/attributes.c
@@ -75,6 +75,7 @@ enum
   C_IFD = 0,
   C_TAG,
   C_VALUE,
+  C_SORT,
   NUM_COL
 };
 
@@ -459,9 +460,8 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
   GtkTreeView    *xmp_treeview;
   GtkTreeView    *iptc_treeview;
   GtkWidget      *attributes_notebook;
-  GHashTableIter  hash_iter;
-  GHashTable     *table;
-  gpointer        p_key, p_value;
+  GList          *iter_list   = NULL;
+  GimpAttribute  *attribute   = NULL;
 
   exif_store = GTK_TREE_STORE (gtk_builder_get_object (builder,
                                                        "exif-treestore"));
@@ -480,29 +480,26 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
   attributes_notebook = GTK_WIDGET (gtk_builder_get_object (builder,
                                                        "attributes-notebook"));
 
-  table = gimp_attributes_get_table (attributes);
+  gimp_attributes_iter_init (attributes, &iter_list);
 
-  g_hash_table_iter_init (&hash_iter, table);
-
-  while (g_hash_table_iter_next (&hash_iter, &p_key, &p_value))
+  while (gimp_attributes_iter_next (attributes, &attribute, &iter_list))
     {
       const gchar    *name;
       const gchar    *type;
       const gchar    *ifd;
       const gchar    *tag;
       const gchar    *value;
+      const gchar    *tag_sorted;
       gchar          *value_utf;
-      GimpAttribute  *attribute;
       GtkTreeIter    *parent = NULL;
       GtkTreeIter    *iter = g_slice_new (GtkTreeIter);
 
-      attribute = (GimpAttribute *) p_value;
-
-      name      = gimp_attribute_get_name (attribute);
-      type      = gimp_attribute_get_attribute_type (attribute);
-      ifd       = gimp_attribute_get_attribute_ifd (attribute);
-      tag       = gimp_attribute_get_attribute_tag (attribute);
-      value     = gimp_attribute_get_interpreted_string (attribute);
+      name       = gimp_attribute_get_name (attribute);
+      type       = gimp_attribute_get_attribute_type (attribute);
+      ifd        = gimp_attribute_get_attribute_ifd (attribute);
+      tag        = gimp_attribute_get_attribute_tag (attribute);
+      tag_sorted = gimp_attribute_get_sortable_name (attribute);
+      value      = gimp_attribute_get_interpreted_string (attribute);
 
       value_utf = g_locale_to_utf8 (value, -1, NULL, NULL, NULL);
 
@@ -521,6 +518,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, ifd,
                                     C_TAG, "",
                                     C_VALUE, "",
+                                    C_SORT, "",
                                     -1);
                 parent = iter;
                 gtk_tree_store_append (exif_store, &child, parent);
@@ -528,6 +526,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, "",
                                     C_TAG, tag,
                                     C_VALUE, value_utf,
+                                    C_SORT, tag_sorted,
                                     -1);
                 attributes_add_parent (type, ifd, parent);
               }
@@ -538,6 +537,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, "",
                                     C_TAG, tag,
                                     C_VALUE, value_utf,
+                                    C_SORT, tag_sorted,
                                     -1);
               }
           }
@@ -552,6 +552,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, ifd,
                                     C_TAG, "",
                                     C_VALUE, "",
+                                    C_SORT, "",
                                     -1);
                 parent = iter;
                 gtk_tree_store_append (xmp_store, &child, parent);
@@ -559,6 +560,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, "",
                                     C_TAG, tag,
                                     C_VALUE, value_utf,
+                                    C_SORT, tag_sorted,
                                     -1);
                 attributes_add_parent (type, ifd, parent);
               }
@@ -569,6 +571,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, "",
                                     C_TAG, tag,
                                     C_VALUE, value_utf,
+                                    C_SORT, tag_sorted,
                                     -1);
               }
           }
@@ -583,6 +586,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, ifd,
                                     C_TAG, "",
                                     C_VALUE, "",
+                                    C_SORT, "",
                                     -1);
                 parent = iter;
                 gtk_tree_store_append (iptc_store, &child, parent);
@@ -590,6 +594,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, "",
                                     C_TAG, tag,
                                     C_VALUE, value_utf,
+                                    C_SORT, tag_sorted,
                                     -1);
                 attributes_add_parent (type, ifd, parent);
               }
@@ -600,6 +605,7 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
                                     C_IFD, "",
                                     C_TAG, tag,
                                     C_VALUE, value_utf,
+                                    C_SORT, tag_sorted,
                                     -1);
               }
           }
@@ -623,14 +629,14 @@ attributes_dialog_set_attributes (GimpAttributes *attributes,
     }
   gtk_tree_view_expand_all (exif_treeview);
   gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(exif_store),
-                                       C_TAG, GTK_SORT_ASCENDING);
+                                       C_SORT, GTK_SORT_ASCENDING);
 
   gtk_tree_view_expand_all (xmp_treeview);
   gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(xmp_store),
-                                       C_TAG, GTK_SORT_ASCENDING);
+                                       C_SORT, GTK_SORT_ASCENDING);
   gtk_tree_view_expand_all (iptc_treeview);
   gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(iptc_store),
-                                       C_TAG, GTK_SORT_ASCENDING);
+                                       C_SORT, GTK_SORT_ASCENDING);
 }
 
 static GtkTreeIter *
diff --git a/plug-ins/ui/plug-in-attributes.ui b/plug-ins/ui/plug-in-attributes.ui
index 951bf4a..cac94dc 100644
--- a/plug-ins/ui/plug-in-attributes.ui
+++ b/plug-ins/ui/plug-in-attributes.ui
@@ -2,16 +2,6 @@
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
   <!-- interface-naming-policy toplevel-contextual -->
-  <object class="GtkTreeStore" id="exif-treestore">
-    <columns>
-      <!-- column-name c-exif-ifd -->
-      <column type="gchararray"/>
-      <!-- column-name c-exif-tag -->
-      <column type="gchararray"/>
-      <!-- column-name c-exif-value -->
-      <column type="gchararray"/>
-    </columns>
-  </object>
   <object class="GtkVBox" id="attributes-vbox">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -113,6 +103,7 @@
                 <property name="expander_column">exif_ifd_column</property>
                 <property name="rules_hint">True</property>
                 <property name="search_column">1</property>
+                <property name="enable_grid_lines">vertical</property>
                 <property name="enable_tree_lines">True</property>
                 <child>
                   <object class="GtkTreeViewColumn" id="exif_ifd_column">
@@ -131,7 +122,6 @@
                     <property name="resizable">True</property>
                     <property name="title" translatable="yes">Exif Tag</property>
                     <property name="expand">True</property>
-                    <property name="sort_column_id">1</property>
                     <child>
                       <object class="GtkCellRendererText" id="exif_tag_renderer_text"/>
                       <attributes>
@@ -152,6 +142,15 @@
                     </child>
                   </object>
                 </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="exif_sort_column">
+                    <property name="sizing">fixed</property>
+                    <property name="min_width">1</property>
+                    <property name="max_width">1</property>
+                    <property name="title" translatable="yes">Sort</property>
+                    <property name="sort_column_id">3</property>
+                  </object>
+                </child>
               </object>
             </child>
           </object>
@@ -183,6 +182,7 @@
                 <property name="headers_clickable">False</property>
                 <property name="rules_hint">True</property>
                 <property name="search_column">1</property>
+                <property name="enable_grid_lines">vertical</property>
                 <property name="enable_tree_lines">True</property>
                 <child>
                   <object class="GtkTreeViewColumn" id="xmp_schema_column">
@@ -201,7 +201,6 @@
                     <property name="resizable">True</property>
                     <property name="title" translatable="yes">XMP Property</property>
                     <property name="expand">True</property>
-                    <property name="sort_column_id">1</property>
                     <child>
                       <object class="GtkCellRendererText" id="xmp_tag_cell_renderer"/>
                       <attributes>
@@ -222,6 +221,21 @@
                     </child>
                   </object>
                 </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="xmp_sort_column">
+                    <property name="sizing">fixed</property>
+                    <property name="min_width">1</property>
+                    <property name="max_width">1</property>
+                    <property name="title" translatable="yes">Sort</property>
+                    <property name="sort_column_id">3</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="xmp_sort_cell_renderer"/>
+                      <attributes>
+                        <attribute name="text">3</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
               </object>
             </child>
           </object>
@@ -256,6 +270,7 @@
                 <property name="headers_clickable">False</property>
                 <property name="rules_hint">True</property>
                 <property name="search_column">1</property>
+                <property name="enable_grid_lines">vertical</property>
                 <property name="enable_tree_lines">True</property>
                 <child>
                   <object class="GtkTreeViewColumn" id="iptc_key_column">
@@ -274,7 +289,6 @@
                     <property name="resizable">True</property>
                     <property name="title" translatable="yes">IPTC Tag</property>
                     <property name="expand">True</property>
-                    <property name="sort_column_id">1</property>
                     <child>
                       <object class="GtkCellRendererText" id="iptc_tag_cell_renderer"/>
                       <attributes>
@@ -295,6 +309,21 @@
                     </child>
                   </object>
                 </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="iptc_sort_column">
+                    <property name="sizing">fixed</property>
+                    <property name="min_width">1</property>
+                    <property name="max_width">1</property>
+                    <property name="title" translatable="yes">Sort</property>
+                    <property name="sort_column_id">3</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                      <attributes>
+                        <attribute name="text">3</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
               </object>
             </child>
           </object>
@@ -323,6 +352,18 @@
       </packing>
     </child>
   </object>
+  <object class="GtkTreeStore" id="exif-treestore">
+    <columns>
+      <!-- column-name c-exif-ifd -->
+      <column type="gchararray"/>
+      <!-- column-name c-exif-tag -->
+      <column type="gchararray"/>
+      <!-- column-name c-exif-value -->
+      <column type="gchararray"/>
+      <!-- column-name sortable -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
   <object class="GtkTreeStore" id="iptc-treestore">
     <columns>
       <!-- column-name c-iptc-ifd -->
@@ -331,6 +372,8 @@
       <column type="gchararray"/>
       <!-- column-name c-iptc-value -->
       <column type="gchararray"/>
+      <!-- column-name sortable -->
+      <column type="gchararray"/>
     </columns>
   </object>
   <object class="GtkTreeStore" id="xmp-treestore">
@@ -341,6 +384,8 @@
       <column type="gchararray"/>
       <!-- column-name c-xmp-value -->
       <column type="gchararray"/>
+      <!-- column-name sortable -->
+      <column type="gchararray"/>
     </columns>
   </object>
 </interface>


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