diff options
Diffstat (limited to 'plug-ins/metadata/metadata-editor.c')
-rw-r--r-- | plug-ins/metadata/metadata-editor.c | 4757 |
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; +} |