From 3c57dd931145d43f2b0aef96c4d178135956bf91 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Fri, 19 Apr 2024 05:13:10 +0200
Subject: Adding upstream version 2.10.36.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 plug-ins/metadata/metadata-editor.c | 4757 +++++++++++++++++++++++++++++++++++
 1 file changed, 4757 insertions(+)
 create mode 100644 plug-ins/metadata/metadata-editor.c

(limited to 'plug-ins/metadata/metadata-editor.c')

diff --git a/plug-ins/metadata/metadata-editor.c b/plug-ins/metadata/metadata-editor.c
new file mode 100644
index 0000000..87a2e87
--- /dev/null
+++ b/plug-ins/metadata/metadata-editor.c
@@ -0,0 +1,4757 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * metadata-editor.c
+ * Copyright (C) 2016, 2017 Ben Touchette
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gexiv2/gexiv2.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <libgimp/gimp.h>
+#include <libgimp/gimpui.h>
+
+#include "libgimp/stdplugins-intl.h"
+
+#include "metadata-tags.h"
+#include "metadata-xml.h"
+#include "metadata-impexp.h"
+#include "metadata-misc.h"
+
+#define PLUG_IN_PROC            "plug-in-metadata-editor"
+#define PLUG_IN_BINARY          "metadata-editor"
+#define PLUG_IN_ROLE            "gimp-metadata"
+
+#define DEFAULT_TEMPLATE_FILE   "gimp_metadata_template.xml"
+
+/*  local function prototypes  */
+
+static void       query                          (void);
+static void       run                            (const gchar          *name,
+                                                  gint                 nparams,
+                                                  const GimpParam     *param,
+                                                  gint                *nreturn_vals,
+                                                  GimpParam          **return_vals);
+
+static gboolean metadata_editor_dialog           (gint32               image_id,
+                                                  GimpMetadata        *metadata,
+                                                  GError             **error);
+
+static void metadata_dialog_editor_set_metadata  (GExiv2Metadata      *metadata,
+                                                  GtkBuilder          *builder);
+
+void metadata_editor_write_callback              (GtkWidget           *dialog,
+                                                  GtkBuilder          *builder,
+                                                  gint32               image_id);
+
+static void impex_combo_callback                (GtkComboBoxText      *combo,
+                                                 gpointer              data);
+
+static void gpsaltsys_combo_callback            (GtkComboBoxText      *combo,
+                                                 gpointer              data);
+
+static void remove_substring                    (const gchar          *string,
+                                                 const gchar          *substring);
+
+static gchar * clean_xmp_string                 (const gchar          *value);
+static gchar ** split_metadata_string           (gchar                *value);
+static void     add_to_store                    (gchar                *value,
+                                                 GtkListStore         *liststore,
+                                                 gint                  store_column);
+
+static void     set_tag_string                  (GimpMetadata         *metadata,
+                                                 const gchar          *name,
+                                                 const gchar          *value);
+
+static gchar *  get_phonetype                   (gchar                *cur_value);
+
+static void     write_metadata_tag              (GtkBuilder           *builder,
+                                                 GimpMetadata         *metadata,
+                                                 gchar                *tag,
+                                                 gint                  data_column);
+
+static void     write_metadata_tag_multiple     (GtkBuilder           *builder,
+                                                 GimpMetadata         *metadata,
+                                                 GExiv2StructureType   type,
+                                                 const gchar          *header_tag,
+                                                 gint                  n_columns,
+                                                 const gchar         **column_tags,
+                                                 const gint            special_handling[]);
+
+gboolean hasCreatorTagData                      (GtkBuilder           *builder);
+gboolean hasLocationCreationTagData             (GtkBuilder           *builder);
+gboolean hasImageSupplierTagData                (GtkBuilder           *builder);
+
+void on_date_button_clicked                     (GtkButton            *widget,
+                                                 GtkWidget            *entry_widget,
+                                                 gchar                *tag);
+
+void on_create_date_button_clicked              (GtkButton            *widget,
+                                                 gpointer              data);
+
+void on_patient_dob_date_button_clicked         (GtkButton            *widget,
+                                                 gpointer              data);
+
+void on_study_date_button_clicked               (GtkButton            *widget,
+                                                 gpointer              data);
+
+void on_series_date_button_clicked              (GtkButton            *widget,
+                                                 gpointer              data);
+
+
+static void
+property_release_id_remove_callback             (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+property_release_id_add_callback                (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+model_release_id_remove_callback                (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+model_release_id_add_callback                   (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+shown_location_remove_callback                  (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+shown_location_add_callback                     (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+feat_org_name_add_callback                      (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+feat_org_name_remove_callback                   (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+feat_org_code_add_callback                      (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+feat_org_code_remove_callback                   (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+artwork_object_add_callback                     (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+artwork_object_remove_callback                  (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+reg_entry_add_callback                          (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+reg_entry_remove_callback                       (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+image_creator_add_callback                      (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+image_creator_remove_callback                   (GtkWidget            *widget,
+                                                 gpointer              data);
+
+static void
+copyright_own_add_callback                      (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+copyright_own_remove_callback                   (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+licensor_add_callback                           (GtkWidget            *widget,
+                                                 gpointer              data);
+static void
+licensor_remove_callback                        (GtkWidget            *widget,
+                                                 gpointer              data);
+
+static void
+list_row_remove_callback                        (GtkWidget            *widget,
+                                                 gpointer              data,
+                                                 gchar                *tag);
+
+static void
+list_row_add_callback                           (GtkWidget            *widget,
+                                                 gpointer              data,
+                                                 gchar                *tag);
+
+static gint
+count_tags                                      (GExiv2Metadata       *metadata,
+                                                 const gchar          *header,
+                                                 const gchar         **tags,
+                                                 int                   items);
+
+static gchar **
+get_tags                                        (GExiv2Metadata       *metadata,
+                                                 const gchar          *header,
+                                                 const gchar         **tags,
+                                                 const int             items,
+                                                 const int             count);
+
+static void
+free_tagdata                                    (gchar               **tagdata,
+                                                 gint                  rows,
+                                                 gint                  cols);
+
+gboolean
+hasModelReleaseTagData                          (GtkBuilder           *builder);
+
+gboolean
+hasPropertyReleaseTagData                       (GtkBuilder           *builder);
+
+static void
+organisation_image_code_cell_edited_callback    (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+organisation_image_name_cell_edited_callback    (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+prop_rel_id_cell_edited_callback                (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+loc_sho_sub_loc_cell_edited_callback            (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+loc_sho_city_cell_edited_callback               (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+loc_sho_state_prov_cell_edited_callback         (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+loc_sho_cntry_cell_edited_callback              (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+loc_sho_cntry_iso_cell_edited_callback          (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+reg_org_id_cell_edited_callback                 (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+reg_item_id_cell_edited_callback                (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+aoo_title_cell_edited_callback                  (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+aoo_copyright_notice_cell_edited_callback       (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+aoo_source_inv_cell_edited_callback             (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+aoo_source_cell_edited_callback                 (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+aoo_creator_cell_edited_callback                (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+aoo_date_creat_cell_edited_callback             (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+cr_owner_name_cell_edited_callback              (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+cr_owner_id_cell_edited_callback                (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_name_cell_edited_callback              (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_id_cell_edited_callback                (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_phone1_cell_edited_callback            (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_phone_type1_cell_edited_callback       (GtkCellRendererCombo *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_phone2_cell_edited_callback            (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_phone_type2_cell_edited_callback       (GtkCellRendererCombo *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_email_cell_edited_callback             (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+static void
+licensor_web_cell_edited_callback               (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data);
+
+void
+cell_edited_callback                            (GtkCellRendererText  *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data,
+                                                 int                   index);
+
+void
+cell_edited_callback_combo                      (GtkCellRendererCombo *cell,
+                                                 const gchar          *path_string,
+                                                 const gchar          *new_text,
+                                                 gpointer              data,
+                                                 int                   index);
+
+
+/* local variables */
+
+static int last_gpsaltsys_sel;
+
+gboolean gimpmetadata;
+gboolean force_write;
+
+static const gchar *lang_default = "lang=\"x-default\"";
+static const gchar *seq_default = "type=\"Seq\"";
+static const gchar *bag_default = "type=\"Bag\"";
+
+metadata_editor meta_args;
+
+#define ME_LOG_DOMAIN "metadata-editor"
+
+const GimpPlugInInfo PLUG_IN_INFO =
+{
+  NULL,  /* init_proc  */
+  NULL,  /* quit_proc  */
+  query, /* query_proc */
+  run,   /* run_proc   */
+};
+
+/* ============================================================================
+ * ==[           ]=============================================================
+ * ==[ FUNCTIONS ]=============================================================
+ * ==[           ]=============================================================
+ * ============================================================================
+ */
+
+
+MAIN ()
+
+/* ============================================================================
+ * ==[ QUERY ]=================================================================
+ * ============================================================================
+ */
+
+static void
+query (void)
+{
+  static const GimpParamDef metadata_args[] =
+  {
+    { GIMP_PDB_INT32, "run-mode", "Run mode { RUN-INTERACTIVE (0) }" },
+    { GIMP_PDB_IMAGE, "image",    "Input image"                      }
+  };
+
+  gimp_install_procedure (PLUG_IN_PROC,
+                          N_("Edit metadata (IPTC, EXIF, XMP)"),
+                          "Edit metadata information attached to the "
+                          "current image. Some or all of this metadata "
+                          "will be saved in the file, depending on the output "
+                          "file format.",
+                          "Ben Touchette",
+                          "Ben Touchette",
+                          "2017",
+                          N_("_Edit Metadata"),
+                          "*",
+                          GIMP_PLUGIN,
+                          G_N_ELEMENTS (metadata_args), 0,
+                          metadata_args, NULL);
+
+  gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Image/Metadata");
+}
+
+/* ============================================================================
+ * ==[ RUN ]===================================================================
+ * ============================================================================
+ */
+
+static void
+run (const gchar      *name,
+     gint              nparams,
+     const GimpParam  *param,
+     gint             *nreturn_vals,
+     GimpParam       **return_vals)
+{
+  static GimpParam   values[2];
+  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
+  GError            *error  = NULL;
+
+  *nreturn_vals = 1;
+  *return_vals  = values;
+
+  values[0].type          = GIMP_PDB_STATUS;
+  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
+
+  force_write = FALSE;
+
+  INIT_I18N ();
+  gimp_ui_init (PLUG_IN_BINARY, TRUE);
+
+  if (! strcmp (name, PLUG_IN_PROC))
+    {
+      GimpMetadata *metadata;
+      gint32        image_ID = param[1].data.d_image;
+
+      metadata = gimp_image_get_metadata (image_ID);
+
+      /* Always show metadata dialog so we can add
+         appropriate iptc data as needed. Sometimes
+         license data needs to be added after the
+         fact and the image may not contain metadata
+         but should have it added as needed. */
+
+      if (!metadata)
+        {
+          metadata = gimp_metadata_new ();
+          gimp_image_set_metadata (image_ID, metadata);
+        }
+
+      if (metadata_editor_dialog (image_ID, metadata, &error))
+        status = GIMP_PDB_SUCCESS;
+      else
+        {
+          status = GIMP_PDB_EXECUTION_ERROR;
+          if (error)
+            {
+             *nreturn_vals = 2;
+              values[1].type          = GIMP_PDB_STRING;
+              values[1].data.d_string = error->message;
+            }
+        }
+    }
+  else
+    {
+      status = GIMP_PDB_CALLING_ERROR;
+    }
+
+  values[0].data.d_status = status;
+}
+
+/* ============================================================================
+ * ==[ EDITOR DIALOG UI ]======================================================
+ * ============================================================================
+ */
+
+static GtkWidget *
+builder_get_widget (GtkBuilder  *builder,
+                    const gchar *name)
+{
+  GObject *object = gtk_builder_get_object (builder, name);
+
+  return GTK_WIDGET (object);
+}
+
+static gboolean
+metadata_editor_dialog (gint32         image_id,
+                        GimpMetadata  *g_metadata,
+                        GError       **error)
+{
+  GtkBuilder     *builder;
+  GtkWidget      *dialog;
+  GtkWidget      *metadata_vbox;
+  GtkWidget      *impex_combo;
+  GtkWidget      *content_area;
+  GExiv2Metadata *metadata;
+  gchar          *ui_file;
+  gchar          *title;
+  gchar          *name;
+  GError         *local_error = NULL;
+  gboolean        run;
+
+  metadata = GEXIV2_METADATA (g_metadata);
+
+  builder = gtk_builder_new ();
+
+  meta_args.image_id = image_id;
+  meta_args.builder = builder;
+  meta_args.metadata = metadata;
+  meta_args.filename = g_strconcat (g_get_home_dir (), "/", DEFAULT_TEMPLATE_FILE,
+                                    NULL);
+
+  ui_file = g_build_filename (gimp_data_directory (),
+                              "ui", "plug-ins", "plug-in-metadata-editor.ui", NULL);
+
+  if (! gtk_builder_add_from_file (builder, ui_file, &local_error))
+    {
+      if (! local_error)
+        local_error = g_error_new_literal (G_FILE_ERROR, 0,
+                                           _("Error loading metadata-editor dialog."));
+      g_propagate_error (error, local_error);
+
+      g_free (ui_file);
+      g_object_unref (builder);
+      return FALSE;
+    }
+
+  g_free (ui_file);
+
+  name = gimp_image_get_name (image_id);
+  title = g_strdup_printf (_("Metadata Editor: %s"), name);
+  if (name)
+    g_free (name);
+
+  dialog = gimp_dialog_new (title,
+                            "gimp-metadata-editor-dialog",
+                            NULL, 0,
+                            gimp_standard_help_func, PLUG_IN_PROC,
+                            _("_Cancel"),         GTK_RESPONSE_CANCEL,
+                            _("_Write Metadata"), GTK_RESPONSE_OK,
+                            NULL);
+
+  meta_args.dialog = dialog;
+
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                            GTK_RESPONSE_OK,
+                                            GTK_RESPONSE_CANCEL,
+                                            -1);
+
+  gimp_window_set_transient (GTK_WINDOW (dialog));
+
+  if (title)
+    g_free (title);
+
+  content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+  metadata_vbox = builder_get_widget (builder, "metadata-vbox");
+  impex_combo   = builder_get_widget (builder, "impex_combo");
+
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (impex_combo),
+                                  _("Select:"));
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (impex_combo),
+                                  _("Import metadata"));
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (impex_combo),
+                                  _("Export metadata"));
+  gtk_combo_box_set_active (GTK_COMBO_BOX (impex_combo), 0);
+
+  g_signal_connect (G_OBJECT (impex_combo),
+                    "changed", G_CALLBACK (impex_combo_callback), &meta_args);
+
+  gtk_container_set_border_width (GTK_CONTAINER (metadata_vbox), 12);
+  gtk_box_pack_start (GTK_BOX (content_area), metadata_vbox, TRUE, TRUE, 0);
+
+  metadata_dialog_editor_set_metadata (metadata, builder);
+
+  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
+  if (run)
+    {
+      metadata_editor_write_callback (dialog, builder, image_id);
+    }
+
+  if (meta_args.filename)
+    {
+      g_free (meta_args.filename);
+    }
+
+  return TRUE;
+}
+
+/* ============================================================================
+ * ==[                   ]=====================================================
+ * ==[ PRIVATE FUNCTIONS ]=====================================================
+ * ==[                   ]=====================================================
+ * ============================================================================
+ */
+static void
+remove_substring (const gchar *string,
+                  const gchar *substring)
+{
+  if (string != NULL && substring != NULL && substring[0] != '\0')
+    {
+      gchar *p = strstr (string, substring);
+      if (p)
+        {
+          memmove (p, p + strlen (substring), strlen (p + strlen (substring)) + 1);
+        }
+    }
+}
+
+static gchar *
+clean_xmp_string (const gchar *value)
+{
+  gchar *value_clean;
+  gchar *value_utf8;
+
+  value_clean = g_strdup (value);
+
+  if (strstr (value_clean, lang_default) != NULL)
+    {
+      remove_substring (value_clean, lang_default);
+      if (strstr (value_clean, " ") != NULL)
+        {
+          remove_substring (value_clean, " ");
+        }
+    }
+
+  if (strstr (value_clean, bag_default) != NULL)
+    {
+      remove_substring (value_clean, bag_default);
+      if (strstr (value_clean, " ") != NULL)
+        {
+          remove_substring (value_clean, " ");
+        }
+    }
+
+  if (strstr (value_clean, seq_default) != NULL)
+    {
+      remove_substring (value_clean, seq_default);
+      if (strstr (value_clean, " ") != NULL)
+        {
+          remove_substring (value_clean, " ");
+        }
+    }
+
+  if (! g_utf8_validate (value_clean, -1, NULL))
+    {
+      value_utf8 = g_locale_to_utf8 (value_clean, -1, NULL, NULL, NULL);
+    }
+  else
+    {
+      value_utf8 = g_strdup (value_clean);
+    }
+
+  g_free (value_clean);
+
+  return value_utf8;
+}
+
+/* We split a string and accept "," and ";" as delimiters.
+ * The result needs to be freed with g_strfreev.
+ */
+static gchar **
+split_metadata_string (gchar *value)
+{
+  gchar  **split;
+  gint     item;
+
+  /* Can't use g_strsplit_set since we work with utf-8 here. */
+  split = g_strsplit (g_strdelimit (value, ";", ','), ",", 0);
+
+  for (item = 0; split[item]; item++)
+    {
+      split[item] = g_strstrip(split[item]);
+    }
+
+  return split;
+}
+
+static void
+add_to_store (gchar *value, GtkListStore *liststore, gint store_column)
+{
+  gchar       **strings;
+  gint          cnt = 0;
+  gint          item;
+  GtkTreeIter   iter;
+
+  if (value)
+    {
+      strings = split_metadata_string (value);
+      if (strings)
+        {
+          for (item = 0; strings[item]; item++)
+            {
+              if (strings[item][0] != '\0')
+                {
+                  cnt++;
+
+                  gtk_list_store_append (liststore, &iter);
+                  gtk_list_store_set (liststore, &iter,
+                                      store_column, strings[item],
+                                      -1);
+                }
+            }
+          g_strfreev(strings);
+        }
+    }
+
+  /* If there are less than two rows, add empty ones. */
+  for (item = cnt; item < 2; item++)
+    {
+      gtk_list_store_append (liststore, &iter);
+      gtk_list_store_set (liststore, &iter,
+                          store_column, NULL,
+                          -1);
+    }
+}
+
+static gint
+count_tags (GExiv2Metadata  *metadata,
+            const gchar     *header,
+            const gchar    **tags,
+            gint             items)
+{
+  int   tagcount;
+  gchar tag[256];
+  int   row, col;
+
+  tagcount = 0;
+  for (row = 1; row < 256; row++)
+    {
+      for (col = 0; col < items; col++)
+        {
+          g_snprintf ((gchar *) &tag, 256, "%s[%d]", header, row);
+          g_snprintf ((gchar *) &tag, 256, "%s%s",
+                      (gchar *) &tag, (gchar *) tags[col]);
+          if (gexiv2_metadata_has_tag (metadata, (gchar *) &tag))
+            {
+              tagcount++;
+              break;
+            }
+        }
+    }
+  return tagcount;
+}
+
+static gchar **
+get_tags (GExiv2Metadata  *metadata,
+          const gchar     *header,
+          const gchar    **tags,
+          const gint       items,
+          const gint       count)
+{
+  gchar **tagdata;
+  gchar **_datarow;
+  gchar   tag[256];
+  int     row, col;
+
+  g_return_val_if_fail (header != NULL && tags != NULL, NULL);
+  g_return_val_if_fail (items > 0, NULL);
+
+  if (count <= 0)
+    return NULL;
+  tagdata = g_new0 (gchar *, count);
+  if (! tagdata)
+    return NULL;
+
+  for (row = 1; row < count + 1; row++)
+    {
+      tagdata[row-1] = g_malloc0 (sizeof (gchar *) * items);
+      for (col = 0; col < items; col++)
+        {
+          gchar *value;
+
+          g_snprintf ((gchar *) &tag, 256, "%s[%d]", header, row);
+          g_snprintf ((gchar *) &tag, 256, "%s%s",
+                      (gchar *) &tag, (gchar *) tags[col]);
+
+          value = gexiv2_metadata_get_tag_string (metadata, (gchar *) &tag);
+          g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "get_tags tag: %s, value: %s", (gchar *) &tag, value);
+
+          _datarow = (gchar **) tagdata[row-1];
+          if (_datarow)
+            _datarow[col] = strdup (value);
+        }
+    }
+  return tagdata;
+}
+
+static void
+free_tagdata(gchar **tagdata, gint rows, gint cols)
+{
+  gint    row, col;
+  gchar **tagdatarow;
+
+  for (row = 0; row < rows; row++)
+    {
+      tagdatarow = (gpointer) tagdata[row];
+
+      for (col = 0; col < cols; col++)
+        {
+          g_free (tagdatarow[col]);
+        }
+      g_free (tagdatarow);
+    }
+  g_free (tagdata);
+}
+
+/* ============================================================================
+ * ==[ DATE CALLBACKS ]========================================================
+ * ============================================================================
+ */
+void
+on_create_date_button_clicked (GtkButton *widget,
+                               gpointer   data)
+{
+  on_date_button_clicked (widget, (GtkWidget*)data,
+                          "Xmp.photoshop.DateCreated");
+}
+
+void
+on_patient_dob_date_button_clicked (GtkButton *widget,
+                                    gpointer   data)
+{
+  on_date_button_clicked (widget, (GtkWidget*)data,
+                          "Xmp.DICOM.PatientDOB");
+}
+
+void
+on_study_date_button_clicked (GtkButton *widget,
+                              gpointer   data)
+{
+  on_date_button_clicked (widget, (GtkWidget*)data,
+                          "Xmp.DICOM.StudyDateTime");
+}
+
+void
+on_series_date_button_clicked (GtkButton *widget,
+                               gpointer   data)
+{
+  on_date_button_clicked (widget, (GtkWidget*)data,
+                          "Xmp.DICOM.SeriesDateTime");
+}
+
+void
+on_date_button_clicked (GtkButton *widget,
+                        GtkWidget *entry_widget,
+                        gchar     *tag)
+{
+  GtkBuilder     *builder;
+  GtkWidget      *calendar_dialog;
+  GtkWidget      *calendar_content_area;
+  GtkWidget      *calendar_vbox;
+  GtkWidget      *calendar;
+  const gchar    *date_text;
+  gchar          *ui_file;
+  GError         *error = NULL;
+  GDateTime      *current_datetime;
+  guint           year, month, day;
+
+  builder = gtk_builder_new ();
+
+  ui_file = g_build_filename (gimp_data_directory (),
+                              "ui", "plug-ins",
+                              "plug-in-metadata-editor-calendar.ui", NULL);
+
+  if (! gtk_builder_add_from_file (builder, ui_file, &error))
+    {
+      g_log ("", G_LOG_LEVEL_MESSAGE,
+             _("Error loading calendar. %s"),
+             error ? error->message : "");
+      g_clear_error (&error);
+
+      if (ui_file)
+        g_free (ui_file);
+      g_object_unref (builder);
+      return;
+    }
+
+  if (ui_file)
+    g_free (ui_file);
+
+  date_text = gtk_entry_get_text (GTK_ENTRY (entry_widget));
+  if (date_text && date_text[0] != '\0')
+    {
+      sscanf (date_text, "%d-%d-%d;", &year, &month, &day);
+      month--;
+    }
+  else
+    {
+      current_datetime = g_date_time_new_now_local ();
+      year = g_date_time_get_year (current_datetime);
+      month = g_date_time_get_month (current_datetime) - 1;
+      day = g_date_time_get_day_of_month (current_datetime);
+    }
+
+  calendar_dialog =
+    gtk_dialog_new_with_buttons (_("Calendar Date:"),
+                                 NULL,
+                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                 _("_Cancel"),  GTK_RESPONSE_CANCEL,
+                                 _("Set Date"), GTK_RESPONSE_OK,
+                                 NULL);
+
+  gtk_dialog_set_default_response (GTK_DIALOG (calendar_dialog),
+                                   GTK_RESPONSE_OK);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (calendar_dialog),
+                                            GTK_RESPONSE_OK,
+                                            GTK_RESPONSE_CANCEL,
+                                            -1);
+
+  gimp_window_set_transient (GTK_WINDOW (calendar_dialog));
+
+  calendar_content_area = gtk_dialog_get_content_area (GTK_DIALOG (
+                            calendar_dialog));
+
+  calendar_vbox = builder_get_widget (builder, "calendar-vbox");
+
+  gtk_container_set_border_width (GTK_CONTAINER (calendar_vbox), 12);
+  gtk_box_pack_start (GTK_BOX (calendar_content_area), calendar_vbox, TRUE, TRUE,
+                      0);
+
+  calendar = builder_get_widget (builder, "calendar");
+
+  gtk_calendar_select_month (GTK_CALENDAR (calendar), month, year);
+  gtk_calendar_select_day (GTK_CALENDAR (calendar), day);
+  gtk_calendar_mark_day (GTK_CALENDAR (calendar), day);
+
+  if (gtk_dialog_run (GTK_DIALOG (calendar_dialog)) == GTK_RESPONSE_OK)
+    {
+      gchar date[25];
+      gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
+      g_sprintf ((gchar*) &date, "%d-%02d-%02d", year, month+1, day);
+      gtk_entry_set_text (GTK_ENTRY (entry_widget), date);
+    }
+
+  gtk_widget_destroy (calendar_dialog);
+}
+
+/* ============================================================================
+ * ==[ SPECIAL TAGS HANDLERS ]=================================================
+ * ============================================================================
+ */
+
+gboolean
+hasImageSupplierTagData (GtkBuilder *builder)
+{
+  gint loop;
+
+  for (loop = 0; loop < imageSupplierInfoHeader.size; loop++)
+    {
+      GObject     *object;
+      const gchar *text;
+
+      object = gtk_builder_get_object (builder, imageSupplierInfoTags[loop].id);
+
+      if (! strcmp (imageSupplierInfoTags[loop].mode, "single"))
+        {
+          text = gtk_entry_get_text (GTK_ENTRY (object));
+
+          if (text && *text)
+            return TRUE;
+        }
+      else if (! strcmp (imageSupplierInfoTags[loop].mode, "multi"))
+        {
+          text = gtk_entry_get_text (GTK_ENTRY (object));
+
+          if (text && *text)
+            return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+gboolean
+hasLocationCreationTagData (GtkBuilder *builder)
+{
+  gint loop;
+
+  for (loop = 0; loop < locationCreationInfoHeader.size; loop++)
+    {
+      GObject     *object;
+      const gchar *text;
+
+      object = gtk_builder_get_object (builder, locationCreationInfoTags[loop].id);
+
+      if (! strcmp (locationCreationInfoTags[loop].mode, "single"))
+        {
+          text = gtk_entry_get_text (GTK_ENTRY (object));
+
+          if (text && *text)
+            return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+gboolean
+hasModelReleaseTagData (GtkBuilder *builder)
+{
+  return FALSE;
+}
+
+gboolean
+hasPropertyReleaseTagData (GtkBuilder *builder)
+{
+  return FALSE;
+}
+
+
+gboolean
+hasCreatorTagData (GtkBuilder *builder)
+{
+  gboolean has_data = FALSE;
+  gint     loop;
+
+  for (loop = 0; loop < creatorContactInfoHeader.size; loop++)
+    {
+      GObject *object;
+
+      object = gtk_builder_get_object (builder, creatorContactInfoTags[loop].id);
+
+      if (GTK_IS_ENTRY (object))
+        {
+          const gchar *text = gtk_entry_get_text (GTK_ENTRY (object));
+
+          if (text && *text)
+            has_data = TRUE;
+        }
+      else if (GTK_IS_TEXT_VIEW (object))
+        {
+          GtkTextView   *text_view = GTK_TEXT_VIEW (object);
+          GtkTextBuffer *buffer    = gtk_text_view_get_buffer (text_view);
+          GtkTextIter    start;
+          GtkTextIter    end;
+          gchar         *text;
+
+          gtk_text_buffer_get_start_iter (buffer, &start);
+          gtk_text_buffer_get_end_iter (buffer, &end);
+
+          text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
+
+          if (text && *text)
+            has_data = TRUE;
+
+          if (text)
+            g_free (text);
+        }
+    }
+
+  return has_data;
+}
+
+/* ============================================================================
+ * ==[ SET DIALOG METADATA ]===================================================
+ * ============================================================================
+ */
+
+/* CELL EDITED */
+
+void
+cell_edited_callback (GtkCellRendererText *cell,
+                      const gchar         *path_string,
+                      const gchar         *new_text,
+                      gpointer             data,
+                      int                  index)
+{
+  GtkTreeModel *model;
+  GtkTreePath  *path;
+  GtkTreeIter   iter;
+
+  model = (GtkTreeModel *)data;
+  path = gtk_tree_path_new_from_string (path_string);
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, index,
+                      new_text, -1);
+}
+
+void
+cell_edited_callback_combo (GtkCellRendererCombo *cell,
+                            const gchar          *path_string,
+                            const gchar          *new_text,
+                            gpointer              data,
+                            int                   column)
+{
+  GtkWidget        *widget;
+  GtkTreeModel     *treemodel;
+  GtkListStore     *liststore;
+  GtkTreeIter       iter;
+  GtkTreePath      *path;
+  GtkTreeSelection *selection;
+
+  widget = GTK_WIDGET (data);
+
+  treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+  liststore = GTK_LIST_STORE (treemodel);
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
+
+  if (gtk_tree_selection_get_selected (GTK_TREE_SELECTION (selection),
+                                       NULL, &iter))
+    {
+      path = gtk_tree_model_get_path (treemodel, &iter);
+      gtk_tree_path_free (path);
+      gtk_list_store_set (liststore, &iter, column, new_text, -1);
+    }
+}
+
+static void
+licensor_name_cell_edited_callback (GtkCellRendererText *cell,
+                                    const gchar         *path_string,
+                                    const gchar         *new_text,
+                                    gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 0);
+}
+
+static void
+licensor_id_cell_edited_callback (GtkCellRendererText *cell,
+                                  const gchar         *path_string,
+                                  const gchar         *new_text,
+                                  gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 1);
+}
+
+static void
+licensor_phone1_cell_edited_callback (GtkCellRendererText *cell,
+                                      const gchar         *path_string,
+                                      const gchar         *new_text,
+                                      gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 2);
+}
+
+static void
+licensor_phone_type1_cell_edited_callback (GtkCellRendererCombo *cell,
+                                           const gchar          *path_string,
+                                           const gchar          *new_text,
+                                           gpointer              data)
+{
+  cell_edited_callback_combo (cell, path_string, new_text, data, 3);
+}
+
+static void
+licensor_phone2_cell_edited_callback (GtkCellRendererText *cell,
+                                      const gchar         *path_string,
+                                      const gchar         *new_text,
+                                      gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 4);
+}
+
+static void
+licensor_phone_type2_cell_edited_callback (GtkCellRendererCombo *cell,
+                                           const gchar          *path_string,
+                                           const gchar          *new_text,
+                                           gpointer              data)
+{
+  cell_edited_callback_combo (cell, path_string, new_text, data, 5);
+}
+
+static void
+licensor_email_cell_edited_callback (GtkCellRendererText *cell,
+                                     const gchar         *path_string,
+                                     const gchar         *new_text,
+                                     gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 6);
+}
+
+static void
+licensor_web_cell_edited_callback (GtkCellRendererText *cell,
+                                   const gchar         *path_string,
+                                   const gchar         *new_text,
+                                   gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 7);
+}
+
+static void
+cr_owner_name_cell_edited_callback (GtkCellRendererText *cell,
+                                    const gchar         *path_string,
+                                    const gchar         *new_text,
+                                    gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 0);
+}
+
+static void
+cr_owner_id_cell_edited_callback (GtkCellRendererText *cell,
+                                  const gchar         *path_string,
+                                  const gchar         *new_text,
+                                  gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 1);
+}
+
+static void
+img_cr8_name_cell_edited_callback (GtkCellRendererText *cell,
+                                   const gchar         *path_string,
+                                   const gchar         *new_text,
+                                   gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 0);
+}
+
+static void
+img_cr8_id_cell_edited_callback (GtkCellRendererText *cell,
+                                 const gchar         *path_string,
+                                 const gchar         *new_text,
+                                 gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 1);
+}
+
+static void
+aoo_copyright_notice_cell_edited_callback (GtkCellRendererText *cell,
+                                           const gchar         *path_string,
+                                           const gchar         *new_text,
+                                           gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 5);
+}
+
+static void
+aoo_source_inv_cell_edited_callback (GtkCellRendererText *cell,
+                                     const gchar         *path_string,
+                                     const gchar         *new_text,
+                                     gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 4);
+}
+
+static void
+aoo_source_cell_edited_callback (GtkCellRendererText *cell,
+                                 const gchar         *path_string,
+                                 const gchar         *new_text,
+                                 gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 3);
+}
+
+static void
+aoo_creator_cell_edited_callback (GtkCellRendererText *cell,
+                                  const gchar         *path_string,
+                                  const gchar         *new_text,
+                                  gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 2);
+}
+
+static void
+aoo_date_creat_cell_edited_callback (GtkCellRendererText *cell,
+                                     const gchar         *path_string,
+                                     const gchar         *new_text,
+                                     gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 1);
+}
+
+static void
+aoo_title_cell_edited_callback (GtkCellRendererText *cell,
+                                const gchar         *path_string,
+                                const gchar         *new_text,
+                                gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 0);
+}
+
+static void
+reg_org_id_cell_edited_callback (GtkCellRendererText *cell,
+                                 const gchar         *path_string,
+                                 const gchar         *new_text,
+                                 gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 0);
+}
+
+static void
+reg_item_id_cell_edited_callback (GtkCellRendererText *cell,
+                                  const gchar         *path_string,
+                                  const gchar         *new_text,
+                                  gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 1);
+}
+
+static void
+loc_sho_sub_loc_cell_edited_callback (GtkCellRendererText *cell,
+                                      const gchar         *path_string,
+                                      const gchar         *new_text,
+                                      gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 0);
+}
+
+static void
+loc_sho_city_cell_edited_callback (GtkCellRendererText *cell,
+                                   const gchar         *path_string,
+                                   const gchar         *new_text,
+                                   gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 1);
+}
+
+static void
+loc_sho_state_prov_cell_edited_callback (GtkCellRendererText *cell,
+    const gchar         *path_string,
+    const gchar         *new_text,
+    gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 2);
+}
+
+static void
+loc_sho_cntry_cell_edited_callback (GtkCellRendererText *cell,
+                                    const gchar         *path_string,
+                                    const gchar         *new_text,
+                                    gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 3);
+}
+
+static void
+loc_sho_cntry_iso_cell_edited_callback (GtkCellRendererText *cell,
+                                        const gchar         *path_string,
+                                        const gchar         *new_text,
+                                        gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 4);
+}
+
+static void
+loc_sho_wrld_reg_cell_edited_callback (GtkCellRendererText *cell,
+                                       const gchar         *path_string,
+                                       const gchar         *new_text,
+                                       gpointer             data)
+{
+  cell_edited_callback (cell, path_string, new_text, data, 5);
+}
+
+static void
+prop_rel_id_cell_edited_callback (GtkCellRendererText *cell,
+                                  const gchar         *path_string,
+                                  const gchar         *new_text,
+                                  gpointer             data)
+{
+  GtkTreeModel *model;
+  GtkTreePath  *path;
+  GtkTreeIter   iter;
+  gint          column;
+  model = (GtkTreeModel *)data;
+  path = gtk_tree_path_new_from_string (path_string);
+
+  column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
+                      new_text, -1);
+}
+
+static void
+mod_rel_id_cell_edited_callback (GtkCellRendererText *cell,
+                                 const gchar         *path_string,
+                                 const gchar         *new_text,
+                                 gpointer             data)
+{
+  GtkTreeModel *model;
+  GtkTreePath  *path;
+  GtkTreeIter   iter;
+  gint          column;
+
+  model = (GtkTreeModel *)data;
+  path = gtk_tree_path_new_from_string (path_string);
+
+  column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
+                      new_text, -1);
+}
+
+static void
+organisation_image_name_cell_edited_callback (GtkCellRendererText *cell,
+                                              const gchar         *path_string,
+                                              const gchar         *new_text,
+                                              gpointer             data)
+{
+  GtkTreeModel *model;
+  GtkTreePath  *path;
+  GtkTreeIter   iter;
+  gint          column;
+
+  model = (GtkTreeModel *)data;
+  path = gtk_tree_path_new_from_string (path_string);
+
+  column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
+                      new_text, -1);
+}
+
+static void
+organisation_image_code_cell_edited_callback (GtkCellRendererText *cell,
+                                              const gchar         *path_string,
+                                              const gchar         *new_text,
+                                              gpointer             data)
+{
+  GtkTreeModel *model;
+  GtkTreePath  *path;
+  GtkTreeIter   iter;
+  gint          column;
+
+  model = (GtkTreeModel *)data;
+  path = gtk_tree_path_new_from_string (path_string);
+
+  column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
+                      new_text, -1);
+}
+
+
+/* CELL / ROW REMOVE */
+
+static void
+list_row_remove_callback (GtkWidget *widget,
+                          gpointer   data,
+                          gchar     *tag)
+{
+  GtkBuilder       *builder = data;
+  GtkWidget        *list_widget;
+  GtkListStore     *liststore;
+  GtkTreeIter       iter;
+  GtkTreeModel     *treemodel;
+  GtkTreeSelection *selection;
+  GtkTreePath      *path;
+
+  list_widget = builder_get_widget (builder, tag);
+
+  treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (list_widget));
+  liststore = GTK_LIST_STORE (treemodel);
+
+  selection = gtk_tree_view_get_selection ((GtkTreeView *)list_widget);
+
+  if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+    {
+      gint number_of_rows;
+
+      path = gtk_tree_model_get_path (treemodel, &iter);
+      gtk_list_store_remove (liststore, &iter);
+      gtk_tree_path_free (path);
+
+      number_of_rows = gtk_tree_model_iter_n_children (treemodel, NULL);
+      /* Make sur that two rows are always showing, else it looks ugly. */
+      if (number_of_rows < 2)
+        {
+          gtk_list_store_append (liststore, &iter);
+        }
+    }
+}
+
+static void
+property_release_id_remove_callback (GtkWidget *widget,
+                                     gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.plus.PropertyReleaseID");
+}
+
+static void
+model_release_id_remove_callback (GtkWidget *widget,
+                                  gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.plus.ModelReleaseID");
+}
+
+static void
+shown_location_remove_callback (GtkWidget *widget,
+                                gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.iptcExt.LocationShown");
+}
+
+static void
+feat_org_name_remove_callback (GtkWidget *widget,
+                               gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.iptcExt.OrganisationInImageName");
+}
+
+static void
+feat_org_code_remove_callback (GtkWidget *widget,
+                               gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.iptcExt.OrganisationInImageCode");
+}
+
+static void
+artwork_object_remove_callback (GtkWidget *widget,
+                                gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.iptcExt.ArtworkOrObject");
+}
+
+static void
+reg_entry_remove_callback (GtkWidget *widget,
+                           gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.iptcExt.RegistryId");
+}
+
+static void
+image_creator_remove_callback (GtkWidget *widget,
+                               gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.plus.ImageCreator");
+}
+
+static void
+copyright_own_remove_callback (GtkWidget *widget,
+                               gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.plus.CopyrightOwner");
+}
+
+static void
+licensor_remove_callback (GtkWidget *widget,
+                          gpointer   data)
+{
+  list_row_remove_callback (widget, data, "Xmp.plus.Licensor");
+}
+
+
+/* CELL / ROW ADD */
+
+static void
+list_row_add_callback (GtkWidget *widget,
+                       gpointer   data,
+                       gchar     *tag)
+{
+  GtkBuilder    *builder = data;
+  GtkWidget     *list_widget;
+  GtkListStore  *liststore;
+  GtkTreeIter    iter;
+
+  list_widget = builder_get_widget (builder, tag);
+
+  liststore = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (list_widget)));
+
+  gtk_list_store_append (liststore, &iter);
+}
+
+static void
+property_release_id_add_callback (GtkWidget *widget,
+                                  gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.plus.PropertyReleaseID");
+}
+
+static void
+model_release_id_add_callback (GtkWidget *widget,
+                               gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.plus.ModelReleaseID");
+}
+
+static void
+shown_location_add_callback (GtkWidget *widget,
+                             gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.iptcExt.LocationShown");
+}
+
+static void
+feat_org_name_add_callback (GtkWidget *widget,
+                            gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.iptcExt.OrganisationInImageName");
+}
+
+static void
+feat_org_code_add_callback (GtkWidget *widget,
+                            gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.iptcExt.OrganisationInImageCode");
+}
+
+static void
+artwork_object_add_callback (GtkWidget *widget,
+                             gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.iptcExt.ArtworkOrObject");
+}
+
+static void
+reg_entry_add_callback (GtkWidget *widget,
+                        gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.iptcExt.RegistryId");
+}
+
+static void
+image_creator_add_callback (GtkWidget *widget,
+                            gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.plus.ImageCreator");
+}
+
+static void
+copyright_own_add_callback (GtkWidget *widget,
+                            gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.plus.CopyrightOwner");
+}
+
+static void
+licensor_add_callback (GtkWidget *widget,
+                       gpointer   data)
+{
+  list_row_add_callback (widget, data, "Xmp.plus.Licensor");
+}
+
+const gchar *gpstooltips[] =
+{
+    N_ ("Enter or edit GPS value here.\n"
+        "Valid values consist of 1, 2 or 3 numbers "
+        "(degrees, minutes, seconds), see the following examples:\n"
+        "10deg 15' 20\", or 10\u00b0 15' 20\", or 10:15:20.45, or "
+        "10 15 20, or 10 15.30, or 10.45\n"
+        "Delete all text to remove the current value."),
+    N_ ("Enter or edit GPS altitude value here.\n"
+        "A valid value consists of one number:\n"
+        "e.g. 100, or 12.24\n"
+        "Depending on the selected measurement type "
+        "the value should be entered in meter (m) "
+        "or feet (ft)\n"
+        "Delete all text to remove the current value.")
+};
+
+enum
+{
+  GPS_LONG_LAT_TOOLTIP,
+  GPS_ALTITUDE_TOOLTIP,
+};
+
+/* Set dialog display settings and data */
+
+static void
+metadata_dialog_editor_set_metadata (GExiv2Metadata *metadata,
+                                     GtkBuilder     *builder)
+{
+  GtkWidget *combo_widget;
+  GtkWidget *entry_widget;
+  GtkWidget *text_widget;
+  GtkWidget *button_widget;
+  gint       width, height;
+  gchar     *value;
+  gint       i;
+
+  gint32 numele = n_default_metadata_tags;
+
+  /* Setup Buttons */
+  button_widget = builder_get_widget (builder, "add_licensor_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (licensor_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_licensor_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (licensor_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_copyright_own_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (copyright_own_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_copyright_own_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (copyright_own_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_image_creator_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (image_creator_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_image_creator_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (image_creator_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_reg_entry_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (reg_entry_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_reg_entry_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (reg_entry_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_artwork_object_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (artwork_object_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_artwork_object_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (artwork_object_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_feat_org_code_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (feat_org_code_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_feat_org_code_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (feat_org_code_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_feat_org_name_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (feat_org_name_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_feat_org_name_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (feat_org_name_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_shown_location_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (shown_location_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_shown_location_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (shown_location_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_model_rel_id_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (model_release_id_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_model_rel_id_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (model_release_id_remove_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "add_prop_rel_id_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (property_release_id_add_callback),
+                    builder);
+
+  button_widget = builder_get_widget (builder, "rem_prop_rel_id_button");
+  g_signal_connect (G_OBJECT (button_widget), "clicked",
+                    G_CALLBACK (property_release_id_remove_callback),
+                    builder);
+
+
+  /* Setup Comboboxes */
+  combo_widget = builder_get_widget (builder, "Xmp.xmp.Rating");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                  _("Unrated"));
+  for (i = 1; i < 6; i++)
+    {
+      gchar *display = g_strdup_printf ("%d", i);
+
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      display);
+      g_free (display);
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Xmp.xmpRights.Marked");
+  for (i = 0; i < 3; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (marked[i].display));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Xmp.photoshop.Urgency");
+  for (i = 0; i < 9; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (urgency[i]));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Xmp.plus.MinorModelAgeDisclosure");
+  for (i = 0; i < 13; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (minormodelagedisclosure[i].display));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Xmp.plus.ModelReleaseStatus");
+  for (i = 0; i < n_modelreleasestatus; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (modelreleasestatus[i].display));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+  gtk_widget_get_size_request (combo_widget, &width, &height);
+  gtk_widget_set_size_request (combo_widget, 180, height);
+
+  combo_widget = builder_get_widget (builder, "Xmp.iptcExt.DigitalSourceType");
+  for (i = 0; i < n_digitalsourcetype; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (digitalsourcetype[i].display));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Xmp.plus.PropertyReleaseStatus");
+  for (i = 0; i < 4; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (propertyreleasestatus[i].display));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+  gtk_widget_get_size_request (combo_widget, &width, &height);
+  gtk_widget_set_size_request (combo_widget, 180, height);
+
+  combo_widget = builder_get_widget (builder, "Xmp.DICOM.PatientSex");
+  for (i = 0; i < 4; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (dicom[i].display));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Exif.GPSInfo.GPSLatitudeRef");
+  for (i = 0; i < 3; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (gpslatref[i]));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Exif.GPSInfo.GPSLongitudeRef");
+  for (i = 0; i < 3; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (gpslngref[i]));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "Exif.GPSInfo.GPSAltitudeRef");
+  for (i = 0; i < 3; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (gpsaltref[i]));
+    }
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  combo_widget = builder_get_widget (builder, "GPSAltitudeSystem");
+  for (i = 0; i < 2; i++)
+    {
+      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_widget),
+                                      gettext (gpsaltsys[i]));
+    }
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo_widget), 0);
+
+  g_signal_connect (G_OBJECT (combo_widget), "changed",
+                    G_CALLBACK (gpsaltsys_combo_callback),
+                    builder);
+
+  /* Set up text view heights */
+  for (i = 0; i < numele; i++)
+    {
+      if (! strcmp ("multi", default_metadata_tags[i].mode))
+        {
+          text_widget = builder_get_widget (builder,
+                                            default_metadata_tags[i].tag);
+          gtk_widget_get_size_request (text_widget, &width, &height);
+          gtk_widget_set_size_request (text_widget, width, height + 60);
+        }
+    }
+
+  for (i = 0; i < creatorContactInfoHeader.size; i++)
+    {
+      if (! strcmp ("multi", creatorContactInfoTags[i].mode))
+        {
+          text_widget = builder_get_widget (builder,
+                                            creatorContactInfoTags[i].id);
+          gtk_widget_get_size_request (text_widget, &width, &height);
+          gtk_widget_set_size_request (text_widget, width, height + 60);
+        }
+    }
+
+  /* Set up lists */
+  for (i = 0; i < imageSupplierInfoHeader.size; i++)
+    {
+      GtkWidget *widget;
+
+      widget = builder_get_widget (builder,
+                                   imageSupplierInfoTags[i].id);
+
+      value = gexiv2_metadata_get_tag_interpreted_string (metadata,
+                                                          imageSupplierInfoTags[i].tag);
+
+      if (value)
+        {
+          gchar *value_utf;
+
+          value_utf = clean_xmp_string (value);
+          g_free (value);
+
+          if (! strcmp ("single", imageSupplierInfoTags[i].mode))
+            {
+              gtk_entry_set_text (GTK_ENTRY (widget), value_utf);
+            }
+          else if (! strcmp ("multi", imageSupplierInfoTags[i].mode))
+            {
+              GtkTextBuffer *buffer;
+
+              buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+              gtk_text_buffer_set_text (buffer, value_utf, -1);
+            }
+          g_free (value_utf);
+        }
+    }
+
+  for (i = 0; i < locationCreationInfoHeader.size; i++)
+    {
+      GtkWidget *widget;
+
+      widget = builder_get_widget (builder,
+                                   locationCreationInfoTags[i].id);
+
+      value = gexiv2_metadata_get_tag_interpreted_string (metadata,
+                                                          locationCreationInfoTags[i].tag);
+
+      if (value)
+        {
+          gchar *value_utf;
+
+          value_utf = clean_xmp_string (value);
+          g_free (value);
+
+          if (! strcmp ("single", locationCreationInfoTags[i].mode))
+            {
+              gtk_entry_set_text (GTK_ENTRY (widget), value_utf);
+            }
+          g_free (value_utf);
+        }
+    }
+
+  /* Set up tag data */
+
+  for (i = 0; i < numele; i++)
+    {
+      GtkWidget *widget;
+      gint       index;
+
+      widget = builder_get_widget (builder, default_metadata_tags[i].tag);
+
+      if (! strcmp ("Exif.GPSInfo.GPSLongitude",
+                    default_metadata_tags[i].tag))
+        {
+          gdouble  gps_value;
+          gchar   *str;
+
+          if (gexiv2_metadata_get_gps_longitude (metadata, &gps_value))
+            {
+              str = metadata_format_gps_longitude_latitude (gps_value);
+              gtk_entry_set_text (GTK_ENTRY (widget), str);
+              g_free (str);
+            }
+          gtk_widget_set_tooltip_text (widget,
+                                       gettext (gpstooltips[GPS_LONG_LAT_TOOLTIP]));
+          continue;
+        }
+      else if (! strcmp ("Exif.GPSInfo.GPSLatitude",
+                         default_metadata_tags[i].tag))
+        {
+          gdouble  gps_value;
+          gchar   *str;
+
+          if (gexiv2_metadata_get_gps_latitude (metadata, &gps_value))
+            {
+              str = metadata_format_gps_longitude_latitude (gps_value);
+              gtk_entry_set_text (GTK_ENTRY (widget), str);
+              g_free (str);
+            }
+          gtk_widget_set_tooltip_text (widget,
+                                       gettext (gpstooltips[GPS_LONG_LAT_TOOLTIP]));
+          continue;
+        }
+      else if (! strcmp ("Exif.GPSInfo.GPSAltitude",
+                        default_metadata_tags[i].tag))
+        {
+          gdouble  gps_value;
+          gchar   *str;
+
+          if (gexiv2_metadata_get_gps_altitude (metadata, &gps_value))
+            {
+              str = metadata_format_gps_altitude (gps_value, TRUE, "");
+              gtk_entry_set_text (GTK_ENTRY (widget), str);
+              g_free (str);
+            }
+          gtk_widget_set_tooltip_text (widget,
+                                       gettext (gpstooltips[GPS_ALTITUDE_TOOLTIP]));
+          continue;
+        }
+
+      index = default_metadata_tags[i].other_tag_index;
+
+      if (default_metadata_tags[i].xmp_type == GIMP_XMP_BAG ||
+          default_metadata_tags[i].xmp_type == GIMP_XMP_SEQ)
+        {
+          gchar **values;
+
+          value = NULL;
+          values = gexiv2_metadata_get_tag_multiple (metadata,
+                                                     default_metadata_tags[i].tag);
+
+          if (values)
+            {
+              gint vi;
+
+              for (vi = 0; values[vi] != NULL; vi++)
+                {
+                  gchar *value_clean;
+
+                  value_clean = clean_xmp_string (values[vi]);
+
+                  if (value_clean != NULL && value_clean[0] != '\0')
+                    {
+                      if (! value)
+                        {
+                          value = g_strdup (value_clean);
+                        }
+                      else
+                        {
+                          gchar *tmpvalue;
+
+                          tmpvalue = value;
+                          value = g_strconcat (value, "\n", value_clean, NULL);
+                          g_free (tmpvalue);
+                        }
+                    }
+                  g_free (value_clean);
+                }
+            }
+
+          if (index > -1)
+            {
+              gchar **equiv_values;
+
+              /* These are all IPTC tags some of which can appear multiple times so
+                * we will use get_tag_multiple. Also IPTC most commonly uses UTF-8
+                * not current locale so get_tag_interpreted was wrong anyway.
+                * FIXME For now lets interpret as UTF-8 and in the future read
+                * and interpret based on the CharacterSet tag.
+                */
+              equiv_values = gexiv2_metadata_get_tag_multiple (metadata,
+                                                        equivalent_metadata_tags[index].tag);
+
+              if (equiv_values)
+                {
+                  gint evi;
+
+                  for (evi = 0; equiv_values[evi] != NULL; evi++)
+                    {
+                      if (equiv_values[evi][0] != '\0')
+                        {
+                          if (! value)
+                            {
+                              value = g_strdup (equiv_values[evi]);
+                            }
+                          else
+                            {
+                              if (! g_strv_contains (values, equiv_values[evi]))
+                                {
+                                  gchar *tmpvalue;
+
+                                  tmpvalue = value;
+                                  value = g_strconcat (value, "\n", equiv_values[evi], NULL);
+                                  g_free (tmpvalue);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+          g_strfreev (values);
+        }
+      else
+        {
+          value = gexiv2_metadata_get_tag_interpreted_string (metadata,
+                                                              default_metadata_tags[i].tag);
+
+          if (value)
+            {
+              gchar *value_utf8 = clean_xmp_string (value);
+
+              g_free (value);
+
+              if (value_utf8 && value_utf8[0] != '\0')
+                {
+                  value = g_strdup (value_utf8);
+                }
+              else
+                {
+                  value = NULL;
+                }
+
+              g_free (value_utf8);
+            }
+
+          if (index > -1)
+            {
+              gchar **values;
+
+              /* It's not very likely we will have an XMP tag that can only
+               * have a single value instead of an array, which corresponds to
+               * an IPTC tag that can have multiple values, but since we
+               * already have this code it can't hurt to keep testing for it.
+               * FIXME For now lets interpret as UTF-8 and in the future read
+               * and interpret based on the CharacterSet tag.
+               */
+              values = gexiv2_metadata_get_tag_multiple (metadata,
+                                                        equivalent_metadata_tags[index].tag);
+
+              if (values)
+                {
+                  gint     i;
+                  GString *str = NULL;
+
+                  for (i = 0; values[i] != NULL; i++)
+                    {
+                      if (values[i][0] != '\0')
+                        {
+                          if (! str)
+                            {
+                              str = g_string_new (values[i]);
+                            }
+                          else
+                            {
+                              if (! strcmp ("multi", equivalent_metadata_tags[index].mode))
+                                {
+                                  g_string_append (str, "\n");
+                                }
+                              else
+                                {
+                                  g_string_append (str, ", ");
+                                }
+                              g_string_append (str, values[i]);
+                            }
+                        }
+                    }
+
+                  if (str)
+                    {
+                      /* If we got values from both Xmp and Iptc then compare those
+                       * values and if they are different concatenate them. Usually they
+                       * should be the same in which case we won't duplicate the string.
+                       */
+                      if (value && strcmp (value, str->str))
+                        {
+                          if (! strcmp ("multi", equivalent_metadata_tags[index].mode))
+                            {
+                              g_string_prepend (str, "\n");
+                            }
+                          else
+                            {
+                              g_string_prepend (str, ", ");
+                            }
+                          g_string_prepend (str, value);
+                          g_free (value);
+                        }
+                      value = g_string_free (str, FALSE);
+                    }
+                }
+            }
+        }
+
+      if (!strcmp ("list", default_metadata_tags[i].mode))
+        {
+          /* Tab: IPTC Extension, Label: Location Shown */
+          if (! strcmp ("Xmp.iptcExt.LocationShown",
+                        default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+              GtkTreeIter        iter;
+              gint               counter;
+              gchar            **tagdata;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              /* LOCATION SHOWN - SUB LOCATION */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LOC_SHO_SUB_LOC);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (loc_sho_sub_loc_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LOC_SHO_SUB_LOC));
+                }
+
+              /* LOCATION SHOWN - CITY */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LOC_SHO_CITY);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (loc_sho_city_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LOC_SHO_CITY));
+                }
+
+              /* LOCATION SHOWN - STATE PROVINCE */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LOC_SHO_STATE_PROV);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (loc_sho_state_prov_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LOC_SHO_STATE_PROV));
+                }
+
+              /* LOCATION SHOWN - COUNTRY */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LOC_SHO_CNTRY);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (loc_sho_cntry_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LOC_SHO_CNTRY));
+                }
+
+              /* LOCATION SHOWN - COUNTRY ISO */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LOC_SHO_CNTRY_ISO);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (loc_sho_cntry_iso_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LOC_SHO_CNTRY_ISO));
+                }
+
+              /* LOCATION SHOWN - WORLD REGION */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LOC_SHO_CNTRY_WRLD_REG);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (loc_sho_wrld_reg_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LOC_SHO_CNTRY_WRLD_REG));
+                }
+
+              /* Favor the most common form: /Iptc4xmpExt:* */
+              counter = count_tags (metadata, LOCATIONSHOWN_HEADER,
+                                    locationshown,
+                                    n_locationshown);
+
+              tagdata = get_tags (metadata, LOCATIONSHOWN_HEADER,
+                                  locationshown,
+                                  n_locationshown, counter);
+
+              if (counter == 0 || ! tagdata)
+                {
+                  /* Alternatively try: /iptcExt:* */
+                  counter = count_tags (metadata, LOCATIONSHOWN_HEADER,
+                                        locationshown_alternative,
+                                        n_locationshown);
+
+                  tagdata = get_tags (metadata, LOCATIONSHOWN_HEADER,
+                                      locationshown_alternative,
+                                      n_locationshown, counter);
+                }
+
+              if (counter > 0 && tagdata)
+                {
+                  gint item;
+
+                  for (item = 0; item < counter; item++)
+                    {
+                      gchar **tagdatarow = (gchar **) tagdata[item];
+
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_LOC_SHO_SUB_LOC,        tagdatarow[0],
+                                          COL_LOC_SHO_CITY,           tagdatarow[1],
+                                          COL_LOC_SHO_STATE_PROV,     tagdatarow[2],
+                                          COL_LOC_SHO_CNTRY,          tagdatarow[3],
+                                          COL_LOC_SHO_CNTRY_ISO,      tagdatarow[4],
+                                          COL_LOC_SHO_CNTRY_WRLD_REG, tagdatarow[5],
+                                          -1);
+                    }
+                  free_tagdata(tagdata, counter, n_locationshown);
+
+                  if (counter == 1)
+                    {
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_LOC_SHO_SUB_LOC,        NULL,
+                                          COL_LOC_SHO_CITY,           NULL,
+                                          COL_LOC_SHO_STATE_PROV,     NULL,
+                                          COL_LOC_SHO_CNTRY,          NULL,
+                                          COL_LOC_SHO_CNTRY_ISO,      NULL,
+                                          COL_LOC_SHO_CNTRY_WRLD_REG, NULL,
+                                          -1);
+                    }
+                }
+              else
+                {
+                  gint item;
+
+                  for (item = 0; item < 2; item++)
+                    {
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_LOC_SHO_SUB_LOC,        NULL,
+                                          COL_LOC_SHO_CITY,           NULL,
+                                          COL_LOC_SHO_STATE_PROV,     NULL,
+                                          COL_LOC_SHO_CNTRY,          NULL,
+                                          COL_LOC_SHO_CNTRY_ISO,      NULL,
+                                          COL_LOC_SHO_CNTRY_WRLD_REG, NULL,
+                                          -1);
+                    }
+                }
+            }
+          /* Tab: IPTC Extension, Label: Featured Organization - Name */
+          else if (! strcmp ("Xmp.iptcExt.OrganisationInImageName",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)),
+                                           GTK_SELECTION_SINGLE);
+
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), 0);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (organisation_image_name_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_ORG_IMG_NAME));
+                }
+
+              add_to_store (value, liststore, COL_ORG_IMG_NAME);
+            }
+          /* Tab: IPTC Extension, Label: Featured Organization - Code */
+          else if (! strcmp ("Xmp.iptcExt.OrganisationInImageCode",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)),
+                                           GTK_SELECTION_SINGLE);
+
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), 0);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (organisation_image_code_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_ORG_IMG_CODE));
+                }
+
+              add_to_store (value, liststore, COL_ORG_IMG_CODE);
+            }
+          /* Tab: IPTC Extension, Label: Artwork or Object */
+          else if (! strcmp ("Xmp.iptcExt.ArtworkOrObject",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+              GtkTreeIter        iter;
+              gint               counter;
+              gchar            **tagdata;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              /* ARTWORK OR OBJECT - TITLE */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_AOO_TITLE);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (aoo_title_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_AOO_TITLE));
+                }
+
+              /* ARTWORK OR OBJECT - DATE CREATED */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_AOO_DATE_CREAT);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r != NULL; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (aoo_date_creat_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_AOO_DATE_CREAT));
+                }
+
+              /* ARTWORK OR OBJECT - CREATOR */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_AOO_CREATOR);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r != NULL; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (aoo_creator_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_AOO_CREATOR));
+                }
+
+              /* ARTWORK OR OBJECT - SOURCE */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_AOO_SOURCE);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (aoo_source_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_AOO_SOURCE));
+                }
+
+              /* ARTWORK OR OBJECT - SOURCE INVENTORY ID */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_AOO_SRC_INV_ID);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (aoo_source_inv_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_AOO_SRC_INV_ID));
+                }
+
+              /* ARTWORK OR OBJECT - COPYRIGHT NOTICE */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_AOO_CR_NOT);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (aoo_copyright_notice_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_AOO_CR_NOT));
+                }
+
+              counter = count_tags (metadata, ARTWORKOROBJECT_HEADER,
+                                    artworkorobject,
+                                    n_artworkorobject);
+
+              tagdata = get_tags (metadata, ARTWORKOROBJECT_HEADER,
+                                  artworkorobject,
+                                  n_artworkorobject, counter);
+
+              if (counter == 0 || ! tagdata)
+                {
+                  /* Alternatively try: /iptcExt:* */
+                  counter = count_tags (metadata, ARTWORKOROBJECT_HEADER,
+                                        artworkorobject_alternative,
+                                        n_artworkorobject);
+
+                  tagdata = get_tags (metadata, ARTWORKOROBJECT_HEADER,
+                                      artworkorobject_alternative,
+                                      n_artworkorobject, counter);
+                }
+
+
+              if (counter > 0 && tagdata)
+                {
+                  gint item;
+
+                  for (item = 0; item < counter; item++)
+                    {
+                      gchar **tagdatarow = (gchar **) tagdata[item];
+
+                      /* remove substring for language id in title field */
+                      remove_substring (tagdatarow[COL_AOO_TITLE], lang_default);
+                      if (strstr (tagdatarow[COL_AOO_TITLE], " "))
+                        {
+                          remove_substring (tagdatarow[COL_AOO_TITLE], " ");
+                        }
+
+                      remove_substring (tagdatarow[COL_AOO_TITLE], bag_default);
+                      if (strstr (tagdatarow[COL_AOO_TITLE], " "))
+                        {
+                          remove_substring (tagdatarow[COL_AOO_TITLE], " ");
+                        }
+
+                      remove_substring (tagdatarow[COL_AOO_TITLE], seq_default);
+                      if (strstr (tagdatarow[COL_AOO_TITLE], " "))
+                        {
+                          remove_substring (tagdatarow[COL_AOO_TITLE], " ");
+                        }
+
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_AOO_TITLE,      tagdatarow[0],
+                                          COL_AOO_DATE_CREAT, tagdatarow[1],
+                                          COL_AOO_CREATOR,    tagdatarow[2],
+                                          COL_AOO_SOURCE,     tagdatarow[3],
+                                          COL_AOO_SRC_INV_ID, tagdatarow[4],
+                                          COL_AOO_CR_NOT,     tagdatarow[5],
+                                          -1);
+                    }
+                  free_tagdata(tagdata, counter, n_artworkorobject);
+                }
+              else
+                {
+                  gint item;
+
+                  for (item = 0; item < 2; item++)
+                    {
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_AOO_TITLE,      NULL,
+                                          COL_AOO_DATE_CREAT, NULL,
+                                          COL_AOO_CREATOR,    NULL,
+                                          COL_AOO_SOURCE,     NULL,
+                                          COL_AOO_SRC_INV_ID, NULL,
+                                          COL_AOO_CR_NOT,     NULL,
+                                          -1);
+                    }
+                }
+            }
+          /* Tab: IPTC Extension, Label: Model Release Identifier */
+          else if (! strcmp ("Xmp.plus.ModelReleaseID",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)),
+                                           GTK_SELECTION_SINGLE);
+
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), 0);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (mod_rel_id_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_PROP_REL_ID));
+                }
+
+              add_to_store (value, liststore, COL_MOD_REL_ID);
+            }
+          /* Tab: IPTC Extension, Label: Registry Entry */
+          else if (! strcmp ("Xmp.iptcExt.RegistryId",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+              GtkTreeIter        iter;
+              gint               counter;
+              gchar            **tagdata;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              /* REGISTRY - ORGANIZATION ID */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_REGISTRY_ORG_ID);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r != NULL; r = r->next)
+                {
+                  renderer = (GtkCellRenderer*) r->data;
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (reg_org_id_cell_edited_callback),
+                                    treemodel);
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_REGISTRY_ORG_ID));
+                }
+
+              /* REGISTRY - ITEM ID */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_REGISTRY_ITEM_ID);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (reg_item_id_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_REGISTRY_ITEM_ID));
+                }
+
+              counter = count_tags (metadata, REGISTRYID_HEADER,
+                                    registryid,
+                                    n_registryid);
+
+              tagdata = get_tags (metadata, REGISTRYID_HEADER,
+                                  registryid,
+                                  n_registryid, counter);
+
+              if (counter == 0 || ! tagdata)
+                {
+                  /* Alternatively try: /iptcExt:* */
+                  counter = count_tags (metadata, REGISTRYID_HEADER,
+                                        registryid_alternative,
+                                        n_registryid);
+
+                  tagdata = get_tags (metadata, REGISTRYID_HEADER,
+                                      registryid_alternative,
+                                      n_registryid, counter);
+                }
+
+              if (counter > 0 && tagdata)
+                {
+                  gint item;
+
+                  for (item = 0; item < counter; item++)
+                    {
+                      gchar **tagdatarow = (gchar **) tagdata[item];
+
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_REGISTRY_ORG_ID,  tagdatarow[0],
+                                          COL_REGISTRY_ITEM_ID, tagdatarow[1],
+                                          -1);
+                    }
+                  free_tagdata(tagdata, counter, n_registryid);
+                }
+              else
+                {
+                  gint item;
+
+                  for (item = 0; item < 2; item++)
+                    {
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_REGISTRY_ORG_ID,  NULL,
+                                          COL_REGISTRY_ITEM_ID, NULL,
+                                          -1);
+                    }
+                }
+            }
+          /* Tab: IPTC Extension, Label: Image Creator */
+          else if (! strcmp ("Xmp.plus.ImageCreator",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+              GtkTreeIter        iter;
+              gint               counter;
+              gchar            **tagdata;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              /* IMAGE CREATOR - NAME */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_IMG_CR8_NAME);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (img_cr8_name_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_IMG_CR8_NAME));
+                }
+
+              /* IMAGE CREATOR - ID */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_IMG_CR8_ID);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (img_cr8_id_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_IMG_CR8_ID));
+                }
+
+                counter = count_tags (metadata, IMAGECREATOR_HEADER,
+                                      imagecreator,
+                                      n_imagecreator);
+
+                tagdata = get_tags (metadata, IMAGECREATOR_HEADER,
+                                    imagecreator,
+                                    n_imagecreator, counter);
+
+                if (counter > 0 && tagdata)
+                  {
+                    gint item;
+
+                    for (item = 0; item < counter; item++)
+                      {
+                        gchar **tagdatarow = (gchar **) tagdata[item];
+
+                        gtk_list_store_append (liststore, &iter);
+                        gtk_list_store_set (liststore, &iter,
+                                            COL_IMG_CR8_NAME, tagdatarow[0],
+                                            COL_IMG_CR8_ID,   tagdatarow[1],
+                                            -1);
+                      }
+                    free_tagdata(tagdata, counter, n_imagecreator);
+                  }
+                else
+                  {
+                    gint item;
+
+                    for (item = 0; item < 2; item++)
+                      {
+                        gtk_list_store_append (liststore, &iter);
+                        gtk_list_store_set (liststore, &iter,
+                                            COL_IMG_CR8_NAME, NULL,
+                                            COL_IMG_CR8_ID,   NULL,
+                                            -1);
+                      }
+                  }
+            }
+          /* Tab: IPTC Extension, Label: Copyright Owner */
+          else if (! strcmp ("Xmp.plus.CopyrightOwner",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+              GtkTreeIter        iter;
+              gint               counter;
+              gchar            **tagdata;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              /* COPYRIGHT OWNER - NAME */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_CR_OWNER_NAME);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (cr_owner_name_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_CR_OWNER_NAME));
+                }
+
+              /* COPYRIGHT OWNER - ID */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_CR_OWNER_ID);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (cr_owner_id_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_CR_OWNER_ID));
+                }
+
+              counter = count_tags (metadata, COPYRIGHTOWNER_HEADER,
+                                    copyrightowner,
+                                    n_copyrightowner);
+
+              tagdata = get_tags (metadata, COPYRIGHTOWNER_HEADER,
+                                  copyrightowner,
+                                  n_copyrightowner, counter);
+
+              if (counter > 0 && tagdata)
+                {
+                  gint item;
+
+                  for (item = 0; item < counter; item++)
+                    {
+                      gchar **tagdatarow = (gchar **) tagdata[item];
+
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_CR_OWNER_NAME, tagdatarow[0],
+                                          COL_CR_OWNER_ID,   tagdatarow[1],
+                                          -1);
+                    }
+                  free_tagdata(tagdata, counter, n_copyrightowner);
+                }
+              else
+                {
+                  gint item;
+
+                  for (item = 0; item < 2; item++)
+                    {
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_CR_OWNER_NAME, NULL,
+                                          COL_CR_OWNER_ID,   NULL,
+                                          -1);
+                    }
+                }
+            }
+          /* Tab: IPTC Extension, Label: Licensor */
+          else if (! strcmp ("Xmp.plus.Licensor",
+                             default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkTreeModel      *phonemodel;
+              GtkListStore      *liststore;
+              GtkListStore      *phonestore;
+              GtkTreeIter        iter;
+              GtkTreeIter        phoneiter;
+              gint               counter;
+              gint               j;
+              gchar            **tagdata;
+
+              phonestore = gtk_list_store_new (1, G_TYPE_STRING);
+              gtk_list_store_append (phonestore, &phoneiter);
+              gtk_list_store_set (phonestore, &phoneiter, 0, "Unknown", -1);
+              for (j=1; j < 6; j++)
+                {
+                  gtk_list_store_append (phonestore, &phoneiter);
+                  gtk_list_store_set (phonestore, &phoneiter,
+                                      0, gettext (phone_types[j].display),
+                                      -1);
+                }
+              phonemodel = GTK_TREE_MODEL (phonestore);
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              /* LICENSOR - NAME */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_NAME);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_name_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_NAME));
+                }
+
+              /* LICENSOR - ID */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_ID);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_id_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_ID));
+                }
+
+              /* LICENSOR - PHONE NUMBER 1 */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_PHONE1);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_phone1_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_PHONE1));
+                }
+
+              /* LICENSOR - PHONE TYPE 1 */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_PHONE_TYPE1);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable",    TRUE,
+                                "text-column", 0,
+                                "has-entry",   FALSE,
+                                "model",       phonemodel,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_phone_type1_cell_edited_callback),
+                                    widget);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_PHONE_TYPE1));
+                }
+
+              /* LICENSOR - PHONE NUMBER 2 */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_PHONE2);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_phone2_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_PHONE2));
+                }
+
+              /* LICENSOR - PHONE TYPE 2 */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_PHONE_TYPE2);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable",    TRUE,
+                                "text-column", 0,
+                                "has-entry",   FALSE,
+                                "model",       phonemodel,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_phone_type2_cell_edited_callback),
+                                    widget);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_PHONE_TYPE2));
+                }
+
+              /* LICENSOR - EMAIL */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_EMAIL);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_email_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_EMAIL));
+                }
+
+              /* LICENSOR - WEB ADDRESS */
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget),
+                                                 COL_LICENSOR_WEB);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (licensor_web_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_LICENSOR_WEB));
+                }
+
+              counter = count_tags (metadata, LICENSOR_HEADER,
+                                    licensor,
+                                    n_licensor);
+
+              tagdata = get_tags (metadata, LICENSOR_HEADER,
+                                  licensor,
+                                  n_licensor, counter);
+
+              if (counter > 0 && tagdata)
+                {
+                  gint item;
+
+                  for (item = 0; item < counter; item++)
+                    {
+                      gchar **tagdatarow = (gchar **) tagdata[item];
+                      gchar   *type1;
+                      gchar   *type2;
+                      gint    types;
+
+                      type1 = g_strdup (gettext (phone_types[0].display));
+                      type2 = g_strdup (gettext (phone_types[0].display));
+
+                      for (types = 0; types < 6; types++)
+                        {
+                          /* phone type 1 */
+                          if (tagdatarow[3] &&
+                              ! strcmp (tagdatarow[3],
+                                        phone_types[types].data))
+                            {
+                              g_free (type1);
+                              type1 = g_strdup (gettext (phone_types[types].display));
+                            }
+
+                          /* phone type 2 */
+                          if (tagdatarow[5] &&
+                              ! strcmp (tagdatarow[5],
+                                        phone_types[types].data))
+                            {
+                              g_free (type2);
+                              type2 = g_strdup (gettext (phone_types[types].display));
+                            }
+                        }
+
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_LICENSOR_NAME,        tagdatarow[0],
+                                          COL_LICENSOR_ID,          tagdatarow[1],
+                                          COL_LICENSOR_PHONE1,      tagdatarow[2],
+                                          COL_LICENSOR_PHONE_TYPE1, type1,
+                                          COL_LICENSOR_PHONE2,      tagdatarow[4],
+                                          COL_LICENSOR_PHONE_TYPE2, type2,
+                                          COL_LICENSOR_EMAIL,       tagdatarow[6],
+                                          COL_LICENSOR_WEB,         tagdatarow[7],
+                                          -1);
+                      g_free (type1);
+                      g_free (type2);
+                    }
+                  free_tagdata(tagdata, counter, n_licensor);
+                }
+              else
+                {
+                  gint item;
+
+                  for (item = 0; item < 2; item++)
+                    {
+                      gtk_list_store_append (liststore, &iter);
+                      gtk_list_store_set (liststore, &iter,
+                                          COL_LICENSOR_NAME,        NULL,
+                                          COL_LICENSOR_ID,          NULL,
+                                          COL_LICENSOR_PHONE1,      NULL,
+                                          COL_LICENSOR_PHONE_TYPE1, gettext (phone_types[0].display),
+                                          COL_LICENSOR_PHONE2,      NULL,
+                                          COL_LICENSOR_PHONE_TYPE1, gettext (phone_types[0].display),
+                                          COL_LICENSOR_EMAIL,       NULL,
+                                          COL_LICENSOR_WEB,         NULL,
+                                          -1);
+                    }
+                }
+            }
+          /* Tab: IPTC Extension, Label: Property Release Identifier */
+          else if (! strcmp ("Xmp.plus.PropertyReleaseID",
+                              default_metadata_tags[i].tag))
+            {
+              GList             *rlist;
+              GList             *r;
+              GtkTreeViewColumn *column;
+              GtkCellRenderer   *renderer;
+              GtkTreeModel      *treemodel;
+              GtkListStore      *liststore;
+
+              treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+              liststore = GTK_LIST_STORE (treemodel);
+
+              gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)),
+                                           GTK_SELECTION_SINGLE);
+
+              column = gtk_tree_view_get_column (GTK_TREE_VIEW (widget), 0);
+              rlist = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+              for (r = rlist; r; r = r->next)
+                {
+                  renderer = r->data;
+
+                  g_object_set (renderer,
+                                "editable", TRUE,
+                                NULL);
+
+                  g_signal_connect (renderer, "edited",
+                                    G_CALLBACK (prop_rel_id_cell_edited_callback),
+                                    treemodel);
+
+                  g_object_set_data (G_OBJECT (renderer),
+                                     "column",
+                                     GINT_TO_POINTER (COL_PROP_REL_ID));
+                }
+
+              add_to_store (value, liststore, COL_PROP_REL_ID);
+            }
+        }
+
+      if (value)
+        {
+          if (! strcmp ("single", default_metadata_tags[i].mode))
+            {
+              gtk_entry_set_text (GTK_ENTRY (widget), value);
+            }
+          else if (! strcmp ("multi", default_metadata_tags[i].mode))
+            {
+              GtkTextBuffer *buffer;
+
+              buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+              gtk_text_buffer_set_text (buffer, value, -1);
+            }
+          else if (! strcmp ("combo", default_metadata_tags[i].mode))
+            {
+              gint32 data = 0;
+
+              if (! strcmp ("Exif.GPSInfo.GPSLatitudeRef",
+                            default_metadata_tags[i].tag))
+                {
+                  if (! strncmp ("N", value, 1))
+                    {
+                      data = 1;
+                    }
+                  else if (! strncmp ("S", value, 1))
+                    {
+                      data = 2;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Exif.GPSInfo.GPSLongitudeRef",
+                                 default_metadata_tags[i].tag))
+                {
+                  if (! strncmp ("E", value, 1))
+                    {
+                      data = 1;
+                    }
+                  else if (! strncmp ("W", value, 1))
+                    {
+                      data = 2;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Exif.GPSInfo.GPSAltitudeRef",
+                                 default_metadata_tags[i].tag))
+                {
+                  if (! strncmp ("A", value, 1))
+                    {
+                      data = 1;
+                    }
+                  else if (! strncmp ("B", value, 1))
+                    {
+                      data = 2;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Xmp.xmp.Rating", default_metadata_tags[i].tag))
+                {
+                  if (! strcmp ("1", value))
+                    {
+                      data = 1;
+                    }
+                  else if (! strcmp ("2", value))
+                    {
+                      data = 2;
+                    }
+                  else if (! strcmp ("3", value))
+                    {
+                      data = 3;
+                    }
+                  else if (! strcmp ("4", value))
+                    {
+                      data = 4;
+                    }
+                  else if (! strcmp ("5", value))
+                    {
+                      data = 5;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Xmp.xmpRights.Marked",
+                                 default_metadata_tags[i].tag))
+                {
+                  if (! strcmp ("True", value))
+                    {
+                      data = 1;
+                    }
+                  else if (! strcmp ("False", value))
+                    {
+                      data = 2;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Xmp.photoshop.Urgency",
+                                 default_metadata_tags[i].tag))
+                {
+                  if (! strcmp ("1", value))
+                    {
+                      data = 1;
+                    }
+                  else if (! strcmp ("2", value))
+                    {
+                      data = 2;
+                    }
+                  else if (! strcmp ("3", value))
+                    {
+                      data = 3;
+                    }
+                  else if (! strcmp ("4", value))
+                    {
+                      data = 4;
+                    }
+                  else if (! strcmp ("5", value))
+                    {
+                      data = 5;
+                    }
+                  else if (! strcmp ("6", value))
+                    {
+                      data = 6;
+                    }
+                  else if (! strcmp ("7", value))
+                    {
+                      data = 7;
+                    }
+                  else if (! strcmp ("8", value))
+                    {
+                      data = 8;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Xmp.plus.MinorModelAgeDisclosure",
+                                 default_metadata_tags[i].tag))
+                {
+                  if (! strcmp ("Age Unknown", value))
+                    {
+                      data = 0;
+                    }
+                  else if (! strcmp ("Age 25 or Over", value))
+                    {
+                      data = 1;
+                    }
+                  else if (! strcmp ("Age 24", value))
+                    {
+                      data = 2;
+                    }
+                  else if (! strcmp ("Age 23", value))
+                    {
+                      data = 3;
+                    }
+                  else if (! strcmp ("Age 22", value))
+                    {
+                      data = 4;
+                    }
+                  else if (! strcmp ("Age 21", value))
+                    {
+                      data = 5;
+                    }
+                  else if (! strcmp ("Age 20", value))
+                    {
+                      data = 6;
+                    }
+                  else if (! strcmp ("Age 19", value))
+                    {
+                      data = 7;
+                    }
+                  else if (! strcmp ("Age 18", value))
+                    {
+                      data = 8;
+                    }
+                  else if (! strcmp ("Age 17", value))
+                    {
+                      data = 9;
+                    }
+                  else if (! strcmp ("Age 16", value))
+                    {
+                      data = 10;
+                    }
+                  else if (! strcmp ("Age 15", value))
+                    {
+                      data = 11;
+                    }
+                  else if (! strcmp ("Age 14 or Under", value))
+                    {
+                      data = 12;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+              else if (! strcmp ("Xmp.plus.ModelReleaseStatus",
+                                 default_metadata_tags[i].tag))
+                {
+                  gint loop;
+
+                  for (loop = 0; loop < n_modelreleasestatus; loop++)
+                    {
+                      if (! strcmp (modelreleasestatus[loop].data, value))
+                        {
+                          gtk_combo_box_set_active (GTK_COMBO_BOX (widget), loop);
+                          break;
+                        }
+
+                      if (! strcmp (gettext (modelreleasestatus[loop].display),
+                                    value))
+                        {
+                          gtk_combo_box_set_active (GTK_COMBO_BOX (widget), loop);
+                          break;
+                        }
+                    }
+                }
+              else if (! strcmp ("Xmp.iptcExt.DigitalSourceType",
+                                 default_metadata_tags[i].tag))
+                {
+                  gint loop;
+
+                  for (loop = 0; loop < n_digitalsourcetype; loop++)
+                    {
+                      if (! strcmp (digitalsourcetype[loop].data, value))
+                        {
+                          gtk_combo_box_set_active (GTK_COMBO_BOX (widget), loop);
+                          break;
+                        }
+
+                      if (! strcmp (gettext (digitalsourcetype[loop].display),
+                                    value))
+                        {
+                          gtk_combo_box_set_active (GTK_COMBO_BOX (widget), loop);
+                          break;
+                        }
+                    }
+                }
+              else if (! strcmp ("Xmp.plus.PropertyReleaseStatus",
+                                 default_metadata_tags[i].tag))
+                {
+                  gint loop;
+
+                  for (loop = 0; loop < 4; loop++)
+                    {
+                      if (! strcmp (propertyreleasestatus[loop].data, value))
+                        {
+                          gtk_combo_box_set_active (GTK_COMBO_BOX (widget), loop);
+                          break;
+                        }
+
+                      if (! strcmp (gettext (propertyreleasestatus[loop].display),
+                                    value))
+                        {
+                          gtk_combo_box_set_active (GTK_COMBO_BOX (widget), loop);
+                          break;
+                        }
+                    }
+                }
+              else if (! strcmp ("Xmp.DICOM.PatientSex",
+                                 default_metadata_tags[i].tag))
+                {
+                  if (! strcmp ("male", value))
+                    {
+                      data = 1;
+                    }
+                  else if (! strcmp ("female", value))
+                    {
+                      data = 2;
+                    }
+                  else if (! strcmp ("other", value))
+                    {
+                      data = 3;
+                    }
+
+                  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), data);
+                }
+            }
+          g_free (value);
+        }
+    }
+
+  /* Set Xmp.iptc.CreatorContactInfo/Iptc4xmpCore:* last since the short form
+   * Xmp.iptc.Ci* could have been used to set this information too. Because
+   * the first (longer) form is the most common let that override the shorter
+   * form in the (unlikely) case that both are present and also have
+   * different values. Due to a bug in the metadata-editor previously only
+   * the short form was saved.
+   */
+  for (i = 0; i < creatorContactInfoHeader.size; i++)
+    {
+      GtkWidget *widget;
+
+      widget = builder_get_widget (builder, creatorContactInfoTags[i].id);
+
+      value = gexiv2_metadata_get_tag_interpreted_string (metadata,
+                                                          creatorContactInfoTags[i].tag);
+
+      if (value)
+        {
+          gchar *value_utf;
+
+          value_utf = clean_xmp_string (value);
+          g_free (value);
+
+          if (! strcmp ("single", creatorContactInfoTags[i].mode))
+            {
+              gtk_entry_set_text (GTK_ENTRY (widget), value_utf);
+            }
+          else if (! strcmp ("multi", creatorContactInfoTags[i].mode))
+            {
+              GtkTextBuffer *buffer;
+              buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
+              gtk_text_buffer_set_text (buffer, value_utf, -1);
+            }
+          g_free (value_utf);
+        }
+    }
+
+  /* Set creation date */
+  entry_widget = builder_get_widget (builder, "create_date_button");
+  g_signal_connect (entry_widget, "clicked",
+                    G_CALLBACK (on_create_date_button_clicked),
+                    builder_get_widget (builder,
+                                        "Xmp.photoshop.DateCreated"));
+
+  /* Set patient dob date */
+  entry_widget = builder_get_widget (builder, "dob_date_button");
+  g_signal_connect (entry_widget, "clicked",
+                    G_CALLBACK (on_patient_dob_date_button_clicked),
+                    builder_get_widget (builder,
+                                        "Xmp.DICOM.PatientDOB"));
+
+  /* Set study date */
+  entry_widget = builder_get_widget (builder, "study_date_button");
+  g_signal_connect (entry_widget, "clicked",
+                    G_CALLBACK (on_study_date_button_clicked),
+                    builder_get_widget (builder,
+                                        "Xmp.DICOM.StudyDateTime"));
+
+  /* Set series date */
+  entry_widget = builder_get_widget (builder, "series_date_button");
+  g_signal_connect (entry_widget, "clicked",
+                    G_CALLBACK (on_series_date_button_clicked),
+                    builder_get_widget (builder,
+                                        "Xmp.DICOM.SeriesDateTime"));
+}
+
+
+/* ============================================================================
+ * ==[ WRITE METADATA ]========================================================
+ * ============================================================================
+ */
+
+static void
+set_tag_failed (const gchar *tag)
+{
+  g_log ("", G_LOG_LEVEL_MESSAGE,
+         _("Failed to set metadata tag %s"), tag);
+}
+
+static void
+set_tag_string (GimpMetadata *metadata,
+                const gchar  *name,
+                const gchar  *value)
+{
+  gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), name);
+
+  if (metadata == NULL) return;
+  if (name == NULL) return;
+  if (value == NULL) return;
+
+  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+                                        name, value))
+    {
+      set_tag_failed (name);
+    }
+}
+
+static gchar *
+get_phonetype (gchar *cur_value)
+{
+  gchar *phone_type_value = NULL;
+  gint   types;
+
+  if (cur_value != NULL)
+    {
+      for (types = 0; types < 6; types++)
+        {
+          if (! strcmp (cur_value, gettext (phone_types[types].display)))
+            {
+              phone_type_value = strdup (phone_types[types].data);
+              break;
+            }
+        }
+      g_free (cur_value);
+    }
+  if (! phone_type_value)
+    phone_type_value = strdup (phone_types[0].data);
+  cur_value = phone_type_value;
+
+  return phone_type_value;
+}
+
+static void
+write_metadata_tag (GtkBuilder *builder, GimpMetadata *metadata, gchar * tag, gint data_column)
+{
+  GtkWidget     *list_widget;
+  GtkTreeModel  *treemodel;
+  gint           row;
+  gint           number_of_rows;
+  gchar         *rc_data;
+  GString       *data;
+
+  list_widget = builder_get_widget (builder, tag);
+  treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (list_widget));
+
+  number_of_rows = gtk_tree_model_iter_n_children (treemodel, NULL);
+
+  if (number_of_rows <= 0)
+    return;
+
+  data = g_string_sized_new (256);
+
+  for (row = 0; row < number_of_rows; row++)
+    {
+      GtkTreeIter iter;
+
+      if (gtk_tree_model_iter_nth_child (treemodel, &iter, NULL, row))
+        {
+          gtk_tree_model_get (treemodel, &iter,
+                              data_column, &rc_data,
+                              -1);
+          if (rc_data && rc_data[0] != '\0')
+            {
+              if (row > 0)
+                g_string_append (data, ", ");
+
+              g_string_append (data, rc_data);
+            }
+          g_free (rc_data);
+        }
+    }
+
+  g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+         "write_metadata_tag tag: %s, value: %s",
+         tag, data->str);
+
+  set_tag_string (metadata, tag, data->str);
+  g_string_free (data, TRUE);
+}
+
+static void
+write_metadata_tag_multiple (GtkBuilder *builder, GimpMetadata *metadata,
+                             GExiv2StructureType type, const gchar * header_tag,
+                             gint n_columns, const gchar **column_tags,
+                             const gint special_handling[])
+{
+  GtkWidget     *list_widget;
+  GtkTreeModel  *treemodel;
+  gint           row;
+  gint           number_of_rows;
+  gint           counter;
+  gchar          temp_tag[1024];
+
+  /* Clear old tag data first */
+  gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), header_tag);
+
+  for (row = 0; row < 256; row++)
+    {
+      gint item;
+
+      for (item = 0; item < n_columns; item++)
+        {
+          g_snprintf (temp_tag, sizeof (temp_tag), "%s[%d]%s",
+                      header_tag, row, locationshown[item]);
+          gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), temp_tag);
+        }
+    }
+
+  list_widget = builder_get_widget (builder, header_tag);
+  treemodel = gtk_tree_view_get_model (GTK_TREE_VIEW (list_widget));
+
+  number_of_rows = gtk_tree_model_iter_n_children (treemodel, NULL);
+
+  if (number_of_rows <= 0)
+    return;
+
+  gexiv2_metadata_set_xmp_tag_struct (GEXIV2_METADATA (metadata),
+                                      header_tag,
+                                      GEXIV2_STRUCTURE_XA_BAG);
+
+  /* We need a separate counter because an empty row will not be written */
+  counter = 1;
+  for (row = 0; row < number_of_rows; row++)
+    {
+      GtkTreeIter iter;
+
+      if (gtk_tree_model_iter_nth_child (treemodel, &iter, NULL, row))
+        {
+          gint col;
+
+          for (col = 0; col < n_columns; col++)
+            {
+              gchar *tag_data;
+
+              gtk_tree_model_get (treemodel, &iter,
+                                  col, &tag_data,
+                                  -1);
+
+              g_snprintf (temp_tag, sizeof (temp_tag), "%s[%d]%s",
+                          header_tag, counter, column_tags[col]);
+
+              if (special_handling)
+                switch(special_handling[col])
+                  {
+                  case METADATA_PHONETYPE:
+                    tag_data = get_phonetype (tag_data);
+                    break;
+                  }
+
+              g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+                     "write_metadata_tag_multiple tag: %s, value: %s, col: %d",
+                     temp_tag, tag_data, col);
+
+              set_tag_string (metadata, temp_tag, tag_data);
+              g_free (tag_data);
+            }
+          counter++;
+        }
+    }
+}
+
+static void
+set_gps_longitude_latitude (GimpMetadata *metadata,
+                            const gchar  *tag,
+                            const gchar  *value)
+{
+  /* \u00b0 - degree symbol */
+  const gchar  delimiters_dms[] = " deg'\":\u00b0";
+  gchar        lng_lat[256];
+  gchar       *s    = g_strdup (value);
+  gchar       *str1 = NULL;
+  gchar       *str2 = NULL;
+  gchar       *str3 = NULL;
+  gdouble      val  = 0.f;
+  gint         degrees, minutes;
+  gdouble      seconds;
+  gboolean     remove_val = FALSE;
+
+  g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "set_gps_longitude_latitude - Tag %s, Input value: %s", tag, value);
+
+  if (s && s[0] != '\0')
+    {
+      str1 = strtok (s, delimiters_dms);
+      str2 = strtok (NULL, delimiters_dms);
+      str3 = strtok (NULL, delimiters_dms);
+
+      g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "String split into: %s - %s - %s", str1, str2, str3);
+    }
+
+  g_free (s);
+
+  if (str1 && str2 && str3)
+    {
+      /* Assuming degrees, minutes, seconds */
+      degrees = g_ascii_strtoll (str1, NULL, 10);
+      minutes = g_ascii_strtoll (str2, NULL, 10);
+      seconds = g_ascii_strtod (str3, NULL);
+    }
+  else if (str1 && str2)
+    {
+      /* Assuming degrees, minutes */
+      gdouble min;
+
+      degrees = g_ascii_strtoll (str1, NULL, 10);
+      min = g_ascii_strtod (str2, NULL);
+      minutes = (gint) min;
+      seconds = (min - (gdouble) minutes) * 60.f;
+    }
+  else if (str1)
+    {
+      /* Assuming degrees only */
+      val = g_ascii_strtod (str1, NULL);
+      degrees = (gint) val;
+      minutes = (gint) ((val - (gdouble) degrees) * 60.f);
+      seconds = ((val - (gdouble) degrees - (gdouble) (minutes / 60.f)) * 60.f * 60.f);
+    }
+  else
+    remove_val = TRUE;
+
+  if (!remove_val)
+    {
+      g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Converted values: %d - %d - %f", degrees, minutes, seconds);
+      g_snprintf (lng_lat, sizeof (lng_lat),
+                  "%d/1 %d/1 %d/1000",
+                  abs (degrees), abs (minutes), abs ((gint) (seconds * 1000.f)));
+      g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Tag: %s, output string: %s", tag, lng_lat);
+
+      if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+                                            tag, lng_lat))
+        {
+          set_tag_failed (tag);
+        }
+    }
+  else
+    {
+      gexiv2_metadata_clear_tag (GEXIV2_METADATA (metadata), tag);
+      g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Removed tag %s (no value).", tag);
+    }
+}
+
+void
+metadata_editor_write_callback (GtkWidget  *dialog,
+                                GtkBuilder *builder,
+                                gint32      image_id)
+{
+  GimpMetadata  *g_metadata;
+  gint           max_elements;
+  gint           i = 0;
+
+  g_metadata = gimp_image_get_metadata (image_id);
+
+  gimp_metadata_add_xmp_history (g_metadata, "metadata");
+
+  write_metadata_tag (builder, g_metadata,
+                      "Xmp.iptcExt.OrganisationInImageName",
+                      COL_ORG_IMG_NAME);
+
+  write_metadata_tag (builder, g_metadata,
+                      "Xmp.iptcExt.OrganisationInImageCode",
+                      COL_ORG_IMG_CODE);
+
+  write_metadata_tag (builder, g_metadata,
+                      "Xmp.plus.ModelReleaseID",
+                      COL_MOD_REL_ID);
+
+  write_metadata_tag (builder, g_metadata,
+                      "Xmp.plus.PropertyReleaseID",
+                      COL_PROP_REL_ID);
+
+  write_metadata_tag_multiple (builder, g_metadata, GEXIV2_STRUCTURE_XA_BAG,
+                               "Xmp.iptcExt.LocationShown",
+                               n_locationshown, locationshown_alternative, NULL);
+
+  write_metadata_tag_multiple (builder, g_metadata, GEXIV2_STRUCTURE_XA_BAG,
+                               "Xmp.iptcExt.ArtworkOrObject",
+                               n_artworkorobject, artworkorobject_alternative, NULL);
+
+  write_metadata_tag_multiple (builder, g_metadata, GEXIV2_STRUCTURE_XA_BAG,
+                               "Xmp.iptcExt.RegistryId",
+                               n_registryid, registryid_alternative, NULL);
+
+  write_metadata_tag_multiple (builder, g_metadata, GEXIV2_STRUCTURE_XA_SEQ,
+                               "Xmp.plus.ImageCreator",
+                               n_imagecreator, imagecreator, NULL);
+
+  write_metadata_tag_multiple (builder, g_metadata, GEXIV2_STRUCTURE_XA_SEQ,
+                               "Xmp.plus.CopyrightOwner",
+                               n_copyrightowner, copyrightowner, NULL);
+
+  write_metadata_tag_multiple (builder, g_metadata, GEXIV2_STRUCTURE_XA_SEQ,
+                               "Xmp.plus.Licensor",
+                               n_licensor, licensor,
+                               licensor_special_handling);
+
+  /* DO CREATOR TAGS */
+
+  if (hasCreatorTagData (builder))
+    {
+      if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                            creatorContactInfoHeader.header,
+                                            "type=\"Struct\""))
+        {
+          set_tag_failed (creatorContactInfoTags[i].tag);
+        }
+
+      for (i = 0; i < creatorContactInfoHeader.size; i++)
+        {
+          GObject *object = gtk_builder_get_object (builder,
+                                                    creatorContactInfoTags[i].id);
+
+          if (! strcmp ("single", creatorContactInfoTags[i].mode))
+            {
+              GtkEntry *entry = GTK_ENTRY (object);
+
+              if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                    creatorContactInfoTags[i].tag,
+                                                    gtk_entry_get_text (entry)))
+                {
+                  set_tag_failed (creatorContactInfoTags[i].tag);
+                }
+            }
+          else if (! strcmp ("multi", creatorContactInfoTags[i].mode))
+            {
+              GtkTextView   *text_view = GTK_TEXT_VIEW (object);
+              GtkTextBuffer *buffer;
+              GtkTextIter    start;
+              GtkTextIter    end;
+              gchar         *text;
+
+              buffer = gtk_text_view_get_buffer (text_view);
+              gtk_text_buffer_get_start_iter (buffer, &start);
+              gtk_text_buffer_get_end_iter (buffer, &end);
+
+              text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
+
+              if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                    creatorContactInfoTags[i].tag,
+                                                    text))
+                {
+                  set_tag_failed (creatorContactInfoTags[i].tag);
+                }
+
+              g_free (text);
+            }
+        }
+    }
+
+  /* DO SINGLE, MULTI AND COMBO TAGS */
+
+  else
+    {
+      gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                 creatorContactInfoHeader.header);
+
+      for (i = 0; i < creatorContactInfoHeader.size; i++)
+        {
+          gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                     creatorContactInfoTags[i].tag);
+        }
+    }
+
+  max_elements = n_default_metadata_tags;
+
+  for (i = 0; i < max_elements; i++)
+    {
+      GObject *object = gtk_builder_get_object (builder,
+                                                default_metadata_tags[i].tag);
+
+      /* SINGLE TAGS */
+
+      if (! strcmp ("single", default_metadata_tags[i].mode))
+        {
+          GtkEntry *entry       = GTK_ENTRY (object);
+          gchar    *value_entry = g_strdup (gtk_entry_get_text (entry));
+
+          if (! strcmp ("Exif.GPSInfo.GPSLongitude",
+                        default_metadata_tags[i].tag) ||
+              ! strcmp ("Exif.GPSInfo.GPSLatitude",
+                        default_metadata_tags[i].tag))
+            {
+              set_gps_longitude_latitude (g_metadata,
+                                          default_metadata_tags[i].tag,
+                                          value_entry);
+            }
+          else if (! strcmp ("Exif.GPSInfo.GPSAltitude",
+                             default_metadata_tags[i].tag))
+            {
+              GtkWidget *combo_widget;
+              gchar      alt_str[256];
+              gdouble    alt_d;
+              gint       msr;
+
+              combo_widget = builder_get_widget (builder,
+                                                 "GPSAltitudeSystem");
+              msr = gtk_combo_box_get_active (GTK_COMBO_BOX (combo_widget));
+
+              alt_d = atof (gtk_entry_get_text (entry));
+              if (msr == 1)
+                alt_d = (alt_d * 12 * 2.54);
+              else
+                alt_d *= 100.f;
+
+              g_snprintf (alt_str, sizeof (alt_str), "%d/100", (gint) alt_d);
+
+              if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                    default_metadata_tags[i].tag,
+                                                    alt_str))
+                {
+                  set_tag_failed (default_metadata_tags[i].tag);
+                }
+            }
+          else
+            {
+              gint         index;
+              const gchar *text_value = gtk_entry_get_text (entry);
+
+              if (default_metadata_tags[i].xmp_type == GIMP_XMP_TEXT ||
+                  default_metadata_tags[i].xmp_type == GIMP_XMP_NONE)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  gexiv2_metadata_set_xmp_tag_struct (GEXIV2_METADATA (g_metadata),
+                                                      default_metadata_tags[i].tag,
+                                                      GEXIV2_STRUCTURE_XA_NONE);
+                  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        default_metadata_tags[i].tag,
+                                                        text_value))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                }
+              else
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        default_metadata_tags[i].tag,
+                                                        text_value))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                }
+
+              index = default_metadata_tags[i].other_tag_index;
+              if (index > -1)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             equivalent_metadata_tags[index].tag);
+                  if (*text_value &&
+                      ! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        equivalent_metadata_tags[index].tag,
+                                                        text_value))
+                    {
+                      set_tag_failed (equivalent_metadata_tags[index].tag);
+                    }
+                }
+            }
+        }
+
+      /* MULTI TAGS */
+
+      else if (! strcmp ("multi", default_metadata_tags[i].mode))
+        {
+          GtkTextView   *text_view = GTK_TEXT_VIEW (object);
+          GtkTextBuffer *buffer;
+          GtkTextIter    start;
+          GtkTextIter    end;
+          gchar         *text;
+          gint           index;
+
+          buffer = gtk_text_view_get_buffer (text_view);
+          gtk_text_buffer_get_start_iter (buffer, &start);
+          gtk_text_buffer_get_end_iter (buffer, &end);
+
+          text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
+
+          gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                     default_metadata_tags[i].tag);
+
+          if (text && *text)
+            {
+              if (default_metadata_tags[i].xmp_type == GIMP_XMP_TEXT ||
+                  default_metadata_tags[i].xmp_type == GIMP_XMP_NONE)
+                {
+                  gexiv2_metadata_set_xmp_tag_struct (GEXIV2_METADATA (g_metadata),
+                                                      default_metadata_tags[i].tag,
+                                                      GEXIV2_STRUCTURE_XA_NONE);
+                  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        default_metadata_tags[i].tag,
+                                                        text))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                }
+              else
+                {
+                  gchar **multi;
+
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+
+                  /* We have one value per line. */
+                  multi = g_strsplit (text, "\n", 0);
+
+                  if (! gexiv2_metadata_set_tag_multiple (GEXIV2_METADATA (g_metadata),
+                                                          default_metadata_tags[i].tag,
+                                                          (const gchar **) multi))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                  g_strfreev (multi);
+                }
+            }
+
+            index = default_metadata_tags[i].other_tag_index;
+            if (index > -1)
+              {
+                gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                           equivalent_metadata_tags[index].tag);
+
+                if (text && *text)
+                  {
+                    if (! strcmp ("multi", equivalent_metadata_tags[index].mode))
+                      {
+                        gchar **multi;
+
+                        multi = g_strsplit (text, "\n", 0);
+
+                        if (! gexiv2_metadata_set_tag_multiple (GEXIV2_METADATA (g_metadata),
+                                                                equivalent_metadata_tags[index].tag,
+                                                                (const gchar **) multi))
+                          {
+                            set_tag_failed (equivalent_metadata_tags[index].tag);
+                          }
+
+                        g_strfreev (multi);
+                      }
+                    else if (! strcmp ("single", equivalent_metadata_tags[index].mode))
+                      {
+                        /* Convert from multiline to single line: keep the \n and just add the whole text. */
+                        if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                              equivalent_metadata_tags[index].tag,
+                                                              text))
+                          {
+                            set_tag_failed (equivalent_metadata_tags[index].tag);
+                          }
+                      }
+                    else
+                      {
+                        g_warning ("Copying from multiline tag %s to %s tag %s not implemented!",
+                                   default_metadata_tags[i].tag,
+                                   equivalent_metadata_tags[index].mode,
+                                   equivalent_metadata_tags[index].tag);
+                      }
+                  }
+              }
+
+          if (text)
+            g_free (text);
+        }
+      else if (! strcmp ("list", default_metadata_tags[i].mode))
+        {
+          /* MIGHT DO SOMETHING HERE */
+        }
+
+      /* COMBO TAGS */
+
+      else if (! strcmp ("combo", default_metadata_tags[i].mode))
+        {
+          GtkComboBoxText *combo;
+          gint32           value;
+
+          combo = GTK_COMBO_BOX_TEXT (object);
+          value = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+          if (! strcmp ("Xmp.photoshop.Urgency", default_metadata_tags[i].tag))
+            {
+              /* IPTC tab - Urgency */
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             "Iptc.Application2.Urgency");
+                }
+              else
+                {
+                  gchar *save;
+
+                  save = g_strdup_printf ("%d", value);
+
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  save);
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  "Iptc.Application2.Urgency",
+                                                  save);
+                  g_free (save);
+                }
+            }
+          else if (! strcmp ("Xmp.xmpRights.Marked",
+                             default_metadata_tags[i].tag))
+            {
+              /* Description tab - Copyright Status */
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                }
+              else
+                {
+                  gchar *save_value;
+
+                  if (value == 1)
+                    save_value = g_strdup_printf ("%s", "True");
+                  else /* (value == 2) */
+                    save_value = g_strdup_printf ("%s", "False");
+
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  save_value);
+                  g_free (save_value);
+                }
+            }
+          else if (! strcmp ("Xmp.xmp.Rating", default_metadata_tags[i].tag))
+            {
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                }
+              else
+                {
+                  gchar *save;
+
+                  save = g_strdup_printf ("%d", value);
+
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  save);
+                  g_free (save);
+                }
+            }
+          else if (! strcmp ("Xmp.DICOM.PatientSex",
+                             default_metadata_tags[i].tag))
+            {
+              switch (value)
+                {
+                case 0:
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  break;
+
+                case 1:
+                  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        default_metadata_tags[i].tag,
+                                                        "male"))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                  break;
+
+                case 2:
+                  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        default_metadata_tags[i].tag,
+                                                        "female"))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                  break;
+
+                case 3:
+                  if (! gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                        default_metadata_tags[i].tag,
+                                                        "other"))
+                    {
+                      set_tag_failed (default_metadata_tags[i].tag);
+                    }
+                  break;
+                }
+            }
+          else if (! strcmp ("Exif.GPSInfo.GPSLongitudeRef",
+                             default_metadata_tags[i].tag))
+            {
+              switch (value)
+                {
+                case 0:
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  break;
+
+                case 1:
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  "E");
+                  break;
+
+                case 2:
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  "W");
+                  break;
+                }
+            }
+          else if (! strcmp ("Exif.GPSInfo.GPSLatitudeRef",
+                             default_metadata_tags[i].tag))
+            {
+              switch (value)
+                {
+                case 0:
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  break;
+
+                case 1:
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  "N");
+                  break;
+
+                case 2:
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  "S");
+                  break;
+                }
+            }
+          else if (! strcmp ("Exif.GPSInfo.GPSAltitudeRef",
+                             default_metadata_tags[i].tag))
+            {
+              switch (value)
+                {
+                case 0:
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                  break;
+
+                case 1:
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  "0");
+                  break;
+
+                case 2:
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  "1");
+                  break;
+                }
+            }
+          else if (! strcmp ("Xmp.plus.ModelReleaseStatus",
+                             default_metadata_tags[i].tag))
+            {
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                }
+              else
+                {
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  modelreleasestatus[value].data);
+                }
+            }
+          else if (! strcmp ("Xmp.plus.PropertyReleaseStatus",
+                             default_metadata_tags[i].tag))
+            {
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                }
+              else
+                {
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  propertyreleasestatus[value].data);
+                }
+            }
+          else if (! strcmp ("Xmp.plus.MinorModelAgeDisclosure",
+                             default_metadata_tags[i].tag))
+            {
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                }
+              else
+                {
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  minormodelagedisclosure[value].data);
+                }
+            }
+          else if (! strcmp ("Xmp.iptcExt.DigitalSourceType",
+                             default_metadata_tags[i].tag))
+            {
+              if (value == 0)
+                {
+                  gexiv2_metadata_clear_tag (GEXIV2_METADATA (g_metadata),
+                                             default_metadata_tags[i].tag);
+                }
+              else
+                {
+                  gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g_metadata),
+                                                  default_metadata_tags[i].tag,
+                                                  digitalsourcetype[value].data);
+                }
+            }
+        }
+    }
+
+  gimp_image_set_metadata (image_id, g_metadata);
+}
+
+/* ============================================================================
+ * ==[ METADATA IMPORT / EXPORT FILE DIALOG UI ]===============================
+ * ============================================================================
+ */
+
+static void
+import_dialog_metadata (metadata_editor *args)
+{
+  GtkWidget *file_dialog;
+  gchar     *filename;
+
+  file_dialog = gtk_file_chooser_dialog_new (_("Import Metadata File"),
+                                             NULL,
+                                             GTK_FILE_CHOOSER_ACTION_OPEN,
+                                             _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                             _("_Import"), GTK_RESPONSE_ACCEPT,
+                                             NULL);
+
+  gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (file_dialog),
+                                 args->filename);
+
+  if (gtk_dialog_run (GTK_DIALOG (file_dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_dialog));
+
+      if (filename)
+        {
+          if (args->filename)
+            {
+              g_free (args->filename);
+            }
+
+          args->filename = g_strdup (filename);
+          import_file_metadata (args);
+        }
+    }
+
+  gtk_widget_destroy (file_dialog);
+}
+
+static void
+export_dialog_metadata (metadata_editor *args)
+{
+  GtkWidget *file_dialog;
+  gchar     *filename;
+
+  file_dialog = gtk_file_chooser_dialog_new (_("Export Metadata File"),
+                                             NULL,
+                                             GTK_FILE_CHOOSER_ACTION_SAVE,
+                                             _("_Cancel"), GTK_RESPONSE_CANCEL,
+                                             _("_Export"), GTK_RESPONSE_ACCEPT,
+                                             NULL);
+
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (file_dialog),
+                                                  TRUE);
+  gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (file_dialog),
+                                 args->filename);
+
+  if (gtk_dialog_run (GTK_DIALOG (file_dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_dialog));
+
+      if (filename)
+        {
+          if (args->filename)
+            {
+              g_free (args->filename);
+            }
+
+          args->filename = g_strdup (filename);
+          export_file_metadata (args);
+        }
+    }
+
+  gtk_widget_destroy (file_dialog);
+}
+
+static void
+impex_combo_callback (GtkComboBoxText *combo,
+                      gpointer         data)
+{
+  metadata_editor *args;
+  gint32           selection;
+
+  args = data;
+  selection = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+  switch (selection)
+    {
+    case 1: /* Import */
+      import_dialog_metadata (args);
+      gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+      break;
+
+    case 2: /* Export */
+      export_dialog_metadata (args);
+      gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+      break;
+    }
+}
+
+
+static void
+gpsaltsys_combo_callback (GtkComboBoxText *combo,
+                          gpointer         data)
+{
+  GtkWidget  *entry;
+  GtkBuilder *builder;
+  gint32      selection;
+  gchar       alt_str[256];
+  double      alt_d;
+
+  builder = data;
+  selection = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+  entry = builder_get_widget (builder, "Exif.GPSInfo.GPSAltitude");
+
+  switch (selection)
+    {
+    case 0: /* Meters */
+      if (last_gpsaltsys_sel != 0)
+        {
+          alt_d = atof (gtk_entry_get_text (GTK_ENTRY (entry)));
+          alt_d = (alt_d * (12 * 2.54)) / 100;
+
+          g_snprintf (alt_str, sizeof (alt_str), "%.2f", (float)alt_d);
+
+          gtk_entry_set_text (GTK_ENTRY (entry), alt_str);
+        }
+      break;
+
+    case 1: /* Feet */
+      if (last_gpsaltsys_sel != 1)
+        {
+          alt_d = atof (gtk_entry_get_text (GTK_ENTRY (entry)));
+          alt_d = alt_d * 3.28;
+
+          g_snprintf (alt_str, sizeof (alt_str), "%.2f", (float)alt_d);
+
+          gtk_entry_set_text (GTK_ENTRY (entry), alt_str);
+        }
+      break;
+    }
+
+  last_gpsaltsys_sel = selection;
+}
-- 
cgit v1.2.3