summaryrefslogtreecommitdiffstats
path: root/plug-ins/metadata/metadata-editor.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:30:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:30:19 +0000
commit5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch)
treecbffb45144febf451e54061db2b21395faf94bfe /plug-ins/metadata/metadata-editor.c
parentInitial commit. (diff)
downloadgimp-5c1676dfe6d2f3c837a5e074117b45613fd29a72.tar.xz
gimp-5c1676dfe6d2f3c837a5e074117b45613fd29a72.zip
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plug-ins/metadata/metadata-editor.c')
-rw-r--r--plug-ins/metadata/metadata-editor.c4757
1 files changed, 4757 insertions, 0 deletions
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;
+}