mirror of https://github.com/GNOME/gimp.git
5655 lines
217 KiB
C
5655 lines
217 KiB
C
/* 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"
|
|
#include "metadata-editor.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"
|
|
|
|
|
|
typedef struct _Metadata Metadata;
|
|
typedef struct _MetadataClass MetadataClass;
|
|
|
|
struct _Metadata
|
|
{
|
|
GimpPlugIn parent_instance;
|
|
};
|
|
|
|
struct _MetadataClass
|
|
{
|
|
GimpPlugInClass parent_class;
|
|
};
|
|
|
|
|
|
#define METADATA_TYPE (metadata_get_type ())
|
|
#define METADATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), METADATA_TYPE, Metadata))
|
|
|
|
GType metadata_get_type (void) G_GNUC_CONST;
|
|
|
|
static GList * metadata_query_procedures (GimpPlugIn *plug_in);
|
|
static GimpProcedure * metadata_create_procedure (GimpPlugIn *plug_in,
|
|
const gchar *name);
|
|
|
|
static GimpValueArray * metadata_run (GimpProcedure *procedure,
|
|
GimpRunMode run_mode,
|
|
GimpImage *image,
|
|
gint n_drawables,
|
|
GimpDrawable **drawables,
|
|
GimpProcedureConfig *config,
|
|
gpointer run_data);
|
|
|
|
|
|
enum
|
|
{
|
|
ME_WIDGET_ENTRY,
|
|
ME_WIDGET_TEXT,
|
|
ME_WIDGET_COMBO,
|
|
ME_WIDGET_DATE_BOX, /* Entry + date select button in a box */
|
|
ME_WIDGET_EC_BOX, /* Entry + combo in a box */
|
|
ME_WIDGET_TREE_GRID, /* Treeview + add/remove row buttons in a box */
|
|
ME_WIDGET_SEPARATOR,
|
|
ME_WIDGET_OTHER,
|
|
};
|
|
|
|
enum
|
|
{
|
|
ME_RENDER_TEXT,
|
|
ME_RENDER_COMBO,
|
|
ME_RENDER_OTHER,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
guint index;
|
|
gchar *label;
|
|
gint widget_type;
|
|
gchar *id;
|
|
gchar *extra_id1; /* date_box: button id; tree view: add button id */
|
|
gchar *extra_id2; /* date_box: icon name for button; tree view: remove button id */
|
|
} me_widget_info;
|
|
|
|
typedef struct
|
|
{
|
|
gchar *label;
|
|
gint renderer_type;
|
|
} me_column_info;
|
|
|
|
static GtkWidget * metadata_editor_create_page_grid (GtkWidget *notebook,
|
|
const gchar *tab_name);
|
|
|
|
static void metadata_editor_create_widgets (const me_widget_info *widget_info,
|
|
gint n_items,
|
|
GtkWidget *grid,
|
|
metadata_editor *meta_info);
|
|
|
|
static void metadata_editor_create_tree_grid (const me_column_info *tree_info,
|
|
gint n_items,
|
|
gint grid_row,
|
|
const me_widget_info *widget_info,
|
|
GtkWidget *grid,
|
|
GtkListStore *store,
|
|
metadata_editor *meta_info);
|
|
|
|
static gboolean metadata_editor_dialog (GimpImage *image,
|
|
GimpMetadata *metadata,
|
|
GError **error);
|
|
|
|
static void metadata_dialog_editor_set_metadata (GExiv2Metadata *metadata,
|
|
metadata_editor *meta_info);
|
|
|
|
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,
|
|
gboolean clear_tag);
|
|
|
|
static gchar * get_phonetype (gchar *cur_value);
|
|
|
|
static void write_metadata_tag (metadata_editor *meta_info,
|
|
GimpMetadata *metadata,
|
|
gchar *tag,
|
|
gint data_column);
|
|
|
|
static void write_metadata_tag_multiple (metadata_editor *meta_info,
|
|
GimpMetadata *metadata,
|
|
GExiv2StructureType type,
|
|
const gchar *header_tag,
|
|
gint n_columns,
|
|
const gchar **column_tags,
|
|
const gint special_handling[]);
|
|
|
|
gboolean hasCreatorTagData (metadata_editor *meta_info);
|
|
gboolean hasLocationCreationTagData (metadata_editor *meta_info);
|
|
gboolean hasImageSupplierTagData (metadata_editor *meta_info);
|
|
|
|
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 (metadata_editor *meta_info);
|
|
|
|
gboolean
|
|
hasPropertyReleaseTagData (metadata_editor *meta_info);
|
|
|
|
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);
|
|
|
|
|
|
G_DEFINE_TYPE (Metadata, metadata, GIMP_TYPE_PLUG_IN)
|
|
|
|
GIMP_MAIN (METADATA_TYPE)
|
|
DEFINE_STD_SET_I18N
|
|
|
|
|
|
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"
|
|
|
|
|
|
/* Widget creation data */
|
|
|
|
static const me_widget_info description_tab_data[] =
|
|
{
|
|
{ 0, N_("Document Title"), ME_WIDGET_ENTRY, "Xmp.dc.title" },
|
|
{ 1, N_("Author"), ME_WIDGET_TEXT, "Xmp.dc.creator" },
|
|
{ 2, N_("Author Title"), ME_WIDGET_ENTRY, "Xmp.photoshop.AuthorsPosition" },
|
|
{ 3, N_("Description"), ME_WIDGET_TEXT, "Xmp.dc.description" },
|
|
{ 4, N_("Description Writer"), ME_WIDGET_ENTRY, "Xmp.photoshop.CaptionWriter" },
|
|
{ 5, N_("Rating"), ME_WIDGET_COMBO, "Xmp.xmp.Rating" },
|
|
{ 6, N_("Keywords"), ME_WIDGET_TEXT, "Xmp.dc.subject" },
|
|
{ 7, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 8, N_("Copyright Status"), ME_WIDGET_COMBO, "Xmp.xmpRights.Marked" },
|
|
{ 9, N_("Copyright Notice"), ME_WIDGET_ENTRY, "Xmp.dc.rights" },
|
|
{ 10, N_("Copyright URL"), ME_WIDGET_ENTRY, "Xmp.xmpRights.WebStatement" },
|
|
};
|
|
static const gint n_description_tab_data = G_N_ELEMENTS (description_tab_data);
|
|
|
|
static const me_widget_info iptc_tab_data[] =
|
|
{
|
|
{ 0, N_("Address"), ME_WIDGET_TEXT, "Xmp.iptc.CiAdrExtadr" },
|
|
{ 1, N_("City"), ME_WIDGET_ENTRY, "Xmp.iptc.CiAdrCity" },
|
|
{ 2, N_("State / Province"), ME_WIDGET_ENTRY, "Xmp.iptc.CiAdrRegion" },
|
|
{ 3, N_("Postal Code"), ME_WIDGET_ENTRY, "Xmp.iptc.CiAdrPcode" },
|
|
{ 4, N_("Country"), ME_WIDGET_ENTRY, "Xmp.iptc.CiAdrCtry" },
|
|
{ 5, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 6, N_("Phone(s)"), ME_WIDGET_TEXT, "Xmp.iptc.CiTelWork" },
|
|
{ 7, N_("E-mail(s)"), ME_WIDGET_TEXT, "Xmp.iptc.CiEmailWork" },
|
|
{ 8, N_("Website(s)"), ME_WIDGET_TEXT, "Xmp.iptc.CiUrlWork" },
|
|
{ 9, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 10, N_("Creation Date"), ME_WIDGET_DATE_BOX, "Xmp.photoshop.DateCreated",
|
|
"create_date_button", "gimp-grid" },
|
|
{ 11, N_("Intellectual Genre"), ME_WIDGET_ENTRY, "Xmp.iptc.IntellectualGenre" },
|
|
{ 12, N_("IPTC Scene Code"), ME_WIDGET_TEXT, "Xmp.iptc.Scene" },
|
|
{ 13, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 14, N_("Sublocation"), ME_WIDGET_ENTRY, "Xmp.iptc.Location" },
|
|
{ 15, N_("City"), ME_WIDGET_ENTRY, "Xmp.photoshop.City" },
|
|
{ 16, N_("State / Province"), ME_WIDGET_ENTRY, "Xmp.photoshop.State" },
|
|
{ 17, N_("Country"), ME_WIDGET_ENTRY, "Xmp.photoshop.Country" },
|
|
{ 18, N_("Country ISO-Code"), ME_WIDGET_ENTRY, "Xmp.iptc.CountryCode" },
|
|
{ 19, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 20, N_("Urgency"), ME_WIDGET_COMBO, "Xmp.photoshop.Urgency" },
|
|
{ 21, N_("Headline"), ME_WIDGET_TEXT, "Xmp.photoshop.Headline" },
|
|
{ 22, N_("IPTC Subject Code"), ME_WIDGET_TEXT, "Xmp.iptc.SubjectCode" },
|
|
{ 23, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 24, N_("Job Identifier"), ME_WIDGET_ENTRY, "Xmp.photoshop.TransmissionReference" },
|
|
{ 25, N_("Instructions"), ME_WIDGET_TEXT, "Xmp.photoshop.Instructions" },
|
|
{ 26, N_("Credit Line"), ME_WIDGET_ENTRY, "Xmp.photoshop.Credit" },
|
|
{ 27, N_("Source"), ME_WIDGET_ENTRY, "Xmp.photoshop.Source" },
|
|
{ 28, N_("Usage Terms"), ME_WIDGET_TEXT, "Xmp.xmpRights.UsageTerms" },
|
|
};
|
|
static const gint n_iptc_tab_data = G_N_ELEMENTS (iptc_tab_data);
|
|
|
|
static const me_widget_info iptc_extension_tab_data[] =
|
|
{
|
|
{ 0, N_("Person Shown"), ME_WIDGET_TEXT, "Xmp.iptcExt.PersonInImage" },
|
|
{ 1, N_("Sublocation"), ME_WIDGET_ENTRY, "Xmp.iptcExt.Sublocation" },
|
|
{ 2, N_("City"), ME_WIDGET_ENTRY, "Xmp.iptcExt.City" },
|
|
{ 3, N_("State / Province"), ME_WIDGET_ENTRY, "Xmp.iptcExt.ProvinceState" },
|
|
{ 4, N_("Country"), ME_WIDGET_ENTRY, "Xmp.iptcExt.CountryName" },
|
|
{ 5, N_("Country ISO-Code"), ME_WIDGET_ENTRY, "Xmp.iptcExt.CountryCode" },
|
|
{ 6, N_("World Region"), ME_WIDGET_ENTRY, "Xmp.iptcExt.WorldRegion" },
|
|
{ 7, N_("Location Shown"), ME_WIDGET_TREE_GRID, "Xmp.iptcExt.LocationShown",
|
|
"add_shown_location_button", "rem_shown_location_button" },
|
|
{ 8, N_("Featured Organization"), ME_WIDGET_TREE_GRID, "Xmp.iptcExt.OrganisationInImageName",
|
|
"add_feat_org_name_button", "rem_feat_org_name_button" },
|
|
{ 9, N_("Organization Code"), ME_WIDGET_TREE_GRID, "Xmp.iptcExt.OrganisationInImageCode",
|
|
"add_feat_org_code_button", "rem_feat_org_code_button" },
|
|
{ 10, N_("Event"), ME_WIDGET_ENTRY, "Xmp.iptcExt.Event" },
|
|
{ 11, N_("Artwork or Object"), ME_WIDGET_TREE_GRID, "Xmp.iptcExt.ArtworkOrObject",
|
|
"add_artwork_object_button", "rem_artwork_object_button" },
|
|
{ 12, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 13, N_("Additional Model Info"), ME_WIDGET_TEXT, "Xmp.iptcExt.AddlModelInfo" },
|
|
{ 14, N_("Model Age"), ME_WIDGET_TEXT, "Xmp.iptcExt.ModelAge" },
|
|
{ 15, N_("Minor Model Age Disclosure"), ME_WIDGET_COMBO, "Xmp.plus.MinorModelAgeDisclosure" },
|
|
{ 16, N_("Model Release Status"), ME_WIDGET_COMBO, "Xmp.plus.ModelReleaseStatus" },
|
|
{ 17, N_("Model Release Identifier"), ME_WIDGET_TREE_GRID, "Xmp.plus.ModelReleaseID",
|
|
"add_model_rel_id_button", "rem_model_rel_id_button" },
|
|
{ 18, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 19, N_("Image Supplier Name"), ME_WIDGET_ENTRY, "Xmp.plus.ImageSupplierName" },
|
|
{ 20, N_("Image Supplier ID"), ME_WIDGET_ENTRY, "Xmp.plus.ImageSupplierID" },
|
|
{ 21, N_("Supplier's Image ID"), ME_WIDGET_ENTRY, "Xmp.plus.ImageSupplierImageID" },
|
|
{ 22, N_("Registry Entry"), ME_WIDGET_TREE_GRID, "Xmp.iptcExt.RegistryId",
|
|
"add_reg_entry_button", "rem_reg_entry_button" },
|
|
{ 23, N_("Max. Available Width"), ME_WIDGET_ENTRY, "Xmp.iptcExt.MaxAvailWidth" },
|
|
{ 24, N_("Max. Available Height"), ME_WIDGET_ENTRY, "Xmp.iptcExt.MaxAvailHeight" },
|
|
{ 25, N_("Digital Source Type"), ME_WIDGET_COMBO, "Xmp.iptcExt.DigitalSourceType" },
|
|
{ 26, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 27, N_("Image Creator"), ME_WIDGET_TREE_GRID, "Xmp.plus.ImageCreator",
|
|
"add_image_creator_button", "rem_image_creator_button" },
|
|
{ 28, N_("Copyright Owner"), ME_WIDGET_TREE_GRID, "Xmp.plus.CopyrightOwner",
|
|
"add_copyright_own_button", "rem_copyright_own_button" },
|
|
{ 29, N_("Licensor"), ME_WIDGET_TREE_GRID, "Xmp.plus.Licensor",
|
|
"add_licensor_button", "rem_licensor_button" },
|
|
{ 30, N_("Property Release Status"), ME_WIDGET_COMBO, "Xmp.plus.PropertyReleaseStatus" },
|
|
{ 31, N_("Property Release Identifier"), ME_WIDGET_TREE_GRID, "Xmp.plus.PropertyReleaseID",
|
|
"add_prop_rel_id_button", "rem_prop_rel_id_button" },
|
|
};
|
|
static const gint n_iptc_extension_tab_data = G_N_ELEMENTS (iptc_extension_tab_data);
|
|
|
|
/* ME_WIDGET_TREE_GRID indexes */
|
|
#define C_LOCATION_SHOWN 7
|
|
#define C_FEATURED_ORG 8
|
|
#define C_FEATURED_ORG_CODE 9
|
|
#define C_ART_OBJECT 11
|
|
#define C_MODEL_RELEASE_ID 17
|
|
#define C_REGISTRY_ENTRY 22
|
|
#define C_IMAGE_CREATOR 27
|
|
#define C_COPYRIGHT_OWNER 28
|
|
#define C_LICENSOR 29
|
|
#define C_PROPERTY_RELEASE_ID 31
|
|
|
|
static const me_column_info location_shown_info[] =
|
|
{
|
|
{ N_("Sublocation"), ME_RENDER_TEXT },
|
|
{ N_("City"), ME_RENDER_TEXT },
|
|
{ N_("Province / State"), ME_RENDER_TEXT },
|
|
{ N_("Country"), ME_RENDER_TEXT },
|
|
{ N_("Country ISO Code"), ME_RENDER_TEXT },
|
|
{ N_("World Region"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_location_shown_info = G_N_ELEMENTS (location_shown_info);
|
|
|
|
static const me_column_info featured_organization_info[] =
|
|
{
|
|
{ N_("Name"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_featured_organization_info = G_N_ELEMENTS (featured_organization_info);
|
|
|
|
static const me_column_info featured_organization_code_info[] =
|
|
{
|
|
{ N_("Code"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_featured_organization_code_info = G_N_ELEMENTS (featured_organization_code_info);
|
|
|
|
static const me_column_info artwork_object_info[] =
|
|
{
|
|
{ N_("Title"), ME_RENDER_TEXT },
|
|
{ N_("Date Created"), ME_RENDER_TEXT },
|
|
{ N_("Creator"), ME_RENDER_TEXT },
|
|
{ N_("Source"), ME_RENDER_TEXT },
|
|
{ N_("Source Inventory ID"), ME_RENDER_TEXT },
|
|
{ N_("Copyright Notice"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_artwork_object_info = G_N_ELEMENTS (artwork_object_info);
|
|
|
|
static const me_column_info model_release_id_info[] =
|
|
{
|
|
{ N_("Model Release Identifier"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_model_release_id_info = G_N_ELEMENTS (model_release_id_info);
|
|
|
|
static const me_column_info registry_entry_info[] =
|
|
{
|
|
{ N_("Organization Identifier"), ME_RENDER_TEXT },
|
|
{ N_("Item Identifier"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_registry_entry_info = G_N_ELEMENTS (registry_entry_info);
|
|
|
|
static const me_column_info image_creator_info[] =
|
|
{
|
|
{ N_("Name"), ME_RENDER_TEXT },
|
|
{ N_("Identifier"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_image_creator_info = G_N_ELEMENTS (image_creator_info);
|
|
|
|
static const me_column_info copyright_owner_info[] =
|
|
{
|
|
{ N_("Name"), ME_RENDER_TEXT },
|
|
{ N_("Identifier"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_copyright_owner_info = G_N_ELEMENTS (copyright_owner_info);
|
|
|
|
static const me_column_info licensor_info[] =
|
|
{
|
|
{ N_("Name"), ME_RENDER_TEXT },
|
|
{ N_("Identifier"), ME_RENDER_TEXT },
|
|
{ N_("Phone Number 1"), ME_RENDER_TEXT },
|
|
{ N_("Phone Type 1"), ME_RENDER_COMBO },
|
|
{ N_("Phone Number 2"), ME_RENDER_TEXT },
|
|
{ N_("Phone Type 2"), ME_RENDER_COMBO },
|
|
{ N_("Email Address"), ME_RENDER_TEXT },
|
|
{ N_("Web Address"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_licensor_info = G_N_ELEMENTS (licensor_info);
|
|
|
|
static const me_column_info property_release_id_info[] =
|
|
{
|
|
{ N_("Identifier"), ME_RENDER_TEXT },
|
|
};
|
|
static const gint n_property_release_id_info = G_N_ELEMENTS (property_release_id_info);
|
|
|
|
|
|
static const me_widget_info categories_labels[] =
|
|
{
|
|
{ 0, N_("Category"), ME_WIDGET_ENTRY, "Xmp.photoshop.Category" },
|
|
{ 1, N_("Supplemental Category"), ME_WIDGET_TEXT, "Xmp.photoshop.SupplementalCategories" },
|
|
};
|
|
static const gint n_categories_labels = G_N_ELEMENTS (categories_labels);
|
|
|
|
static const me_widget_info gps_labels[] =
|
|
{
|
|
{ 0, N_("Longitude"), ME_WIDGET_ENTRY, "Exif.GPSInfo.GPSLongitude" },
|
|
{ 1, N_("Longitude Reference"), ME_WIDGET_COMBO, "Exif.GPSInfo.GPSLongitudeRef" },
|
|
{ 2, N_("Latitude"), ME_WIDGET_ENTRY, "Exif.GPSInfo.GPSLatitude" },
|
|
{ 3, N_("Latitude Reference"), ME_WIDGET_COMBO, "Exif.GPSInfo.GPSLatitudeRef" },
|
|
{ 4, N_("Altitude"), ME_WIDGET_EC_BOX, "Exif.GPSInfo.GPSAltitude",
|
|
"GPSAltitudeSystem" },
|
|
{ 5, N_("Altitude Reference"), ME_WIDGET_COMBO, "Exif.GPSInfo.GPSAltitudeRef" },
|
|
};
|
|
static const gint n_gps_labels = G_N_ELEMENTS (gps_labels);
|
|
|
|
static const me_widget_info dicom_info_labels[] =
|
|
{
|
|
{ 0, N_("Patient"), ME_WIDGET_ENTRY, "Xmp.DICOM.PatientName" },
|
|
{ 1, N_("Patient ID"), ME_WIDGET_ENTRY, "Xmp.DICOM.PatientID" },
|
|
{ 2, N_("Date of Birth"), ME_WIDGET_DATE_BOX, "Xmp.DICOM.PatientDOB",
|
|
"dob_date_button", "gimp-grid" },
|
|
{ 3, N_("Patient Sex"), ME_WIDGET_COMBO, "Xmp.DICOM.PatientSex" },
|
|
{ 4, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 5, N_("Study ID"), ME_WIDGET_ENTRY, "Xmp.DICOM.StudyID" },
|
|
{ 6, N_("Referring Physician"), ME_WIDGET_ENTRY, "Xmp.DICOM.StudyPhysician" },
|
|
{ 7, N_("Study Date"), ME_WIDGET_DATE_BOX, "Xmp.DICOM.StudyDateTime",
|
|
"study_date_button", "gimp-grid" },
|
|
{ 8, N_("Study Description"), ME_WIDGET_TEXT , "Xmp.DICOM.StudyDescription" },
|
|
{ 9, N_("Series Number"), ME_WIDGET_ENTRY, "Xmp.DICOM.SeriesNumber" },
|
|
{ 10, N_("Modality"), ME_WIDGET_ENTRY, "Xmp.DICOM.SeriesModality" },
|
|
{ 11, N_("Series Date"), ME_WIDGET_DATE_BOX, "Xmp.DICOM.SeriesDateTime",
|
|
"series_date_button", "gimp-grid" },
|
|
{ 12, N_("Series Description"), ME_WIDGET_TEXT , "Xmp.DICOM.SeriesDescription" },
|
|
{ 13, "", ME_WIDGET_SEPARATOR, "" },
|
|
{ 14, N_("Equipment Institution"), ME_WIDGET_ENTRY, "Xmp.DICOM.EquipmentInstitution" },
|
|
{ 15, N_("Equipment Manufacturer"), ME_WIDGET_ENTRY, "Xmp.DICOM.EquipmentManufacturer" },
|
|
};
|
|
static const gint n_dicom_info_labels = G_N_ELEMENTS (dicom_info_labels);
|
|
|
|
|
|
static void
|
|
metadata_class_init (MetadataClass *klass)
|
|
{
|
|
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
|
|
|
|
plug_in_class->query_procedures = metadata_query_procedures;
|
|
plug_in_class->create_procedure = metadata_create_procedure;
|
|
plug_in_class->set_i18n = STD_SET_I18N;
|
|
}
|
|
|
|
static void
|
|
metadata_init (Metadata *metadata)
|
|
{
|
|
}
|
|
|
|
static GList *
|
|
metadata_query_procedures (GimpPlugIn *plug_in)
|
|
{
|
|
return g_list_append (NULL, g_strdup (PLUG_IN_PROC));
|
|
}
|
|
|
|
static GimpProcedure *
|
|
metadata_create_procedure (GimpPlugIn *plug_in,
|
|
const gchar *name)
|
|
{
|
|
GimpProcedure *procedure = NULL;
|
|
|
|
if (! strcmp (name, PLUG_IN_PROC))
|
|
{
|
|
procedure = gimp_image_procedure_new (plug_in, name,
|
|
GIMP_PDB_PROC_TYPE_PLUGIN,
|
|
metadata_run, NULL, NULL);
|
|
|
|
gimp_procedure_set_image_types (procedure, "*");
|
|
|
|
gimp_procedure_set_menu_label (procedure, _("_Edit Metadata"));
|
|
gimp_procedure_add_menu_path (procedure, "<Image>/Image/Metadata");
|
|
|
|
gimp_procedure_set_documentation (procedure,
|
|
_("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.",
|
|
name);
|
|
gimp_procedure_set_attribution (procedure,
|
|
"Ben Touchette",
|
|
"Ben Touchette",
|
|
"2017");
|
|
}
|
|
|
|
return procedure;
|
|
}
|
|
|
|
static GimpValueArray *
|
|
metadata_run (GimpProcedure *procedure,
|
|
GimpRunMode run_mode,
|
|
GimpImage *image,
|
|
gint n_drawables,
|
|
GimpDrawable **drawables,
|
|
GimpProcedureConfig *config,
|
|
gpointer run_data)
|
|
{
|
|
GimpMetadata *metadata;
|
|
GError *error = NULL;
|
|
|
|
gimp_ui_init (PLUG_IN_BINARY);
|
|
|
|
metadata = gimp_image_get_metadata (image);
|
|
|
|
/* 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, metadata);
|
|
}
|
|
|
|
if (metadata_editor_dialog (image, metadata, &error))
|
|
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
|
|
else
|
|
return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR, error);
|
|
}
|
|
|
|
|
|
/* ============================================================================
|
|
* ==[ EDITOR DIALOG UI ]======================================================
|
|
* ============================================================================
|
|
*/
|
|
|
|
GtkWidget *
|
|
metadata_editor_get_widget (metadata_editor *meta_info,
|
|
const gchar *name)
|
|
{
|
|
return GTK_WIDGET (g_hash_table_lookup (meta_info->widgets, name));
|
|
}
|
|
|
|
static GtkWidget *
|
|
metadata_editor_create_page_grid (GtkWidget *notebook,
|
|
const gchar *tab_name)
|
|
{
|
|
GtkWidget *scrolled_win;
|
|
GtkWidget *viewport;
|
|
GtkWidget *box;
|
|
GtkWidget *label;
|
|
GtkWidget *grid;
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_show (box);
|
|
|
|
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 6);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
gtk_box_pack_start (GTK_BOX (box), scrolled_win, TRUE, TRUE, 0);
|
|
gtk_widget_show (scrolled_win);
|
|
|
|
label = gtk_label_new (tab_name);
|
|
gtk_widget_set_margin_start (label, 2);
|
|
gtk_widget_set_margin_top (label, 2);
|
|
gtk_widget_set_margin_end (label, 2);
|
|
gtk_widget_set_margin_bottom (label, 2);
|
|
gtk_widget_set_can_focus (label, FALSE);
|
|
gtk_widget_show (label);
|
|
|
|
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), box, label);
|
|
|
|
viewport = gtk_viewport_new (NULL, NULL);
|
|
gtk_container_add (GTK_CONTAINER (scrolled_win), viewport);
|
|
gtk_widget_show (viewport);
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_container_add (GTK_CONTAINER (viewport), box);
|
|
gtk_widget_show (box);
|
|
|
|
grid = gtk_grid_new ();
|
|
gtk_widget_set_margin_bottom (grid, 5);
|
|
gtk_container_set_border_width (GTK_CONTAINER (grid), 6);
|
|
gtk_grid_set_row_spacing (GTK_GRID (grid), 3);
|
|
gtk_grid_set_column_spacing (GTK_GRID (grid), 30);
|
|
gtk_box_pack_start (GTK_BOX (box), grid, FALSE, TRUE, 0);
|
|
gtk_widget_show (grid);
|
|
|
|
return grid;
|
|
}
|
|
|
|
static void
|
|
metadata_editor_create_widgets (const me_widget_info *widget_info,
|
|
gint n_items,
|
|
GtkWidget *grid,
|
|
metadata_editor *meta_info)
|
|
{
|
|
GtkWidget *label;
|
|
|
|
/* Labels on the left, data entry widgets on the right */
|
|
for (int i = 0; i < n_items; i++)
|
|
{
|
|
if (widget_info[i].widget_type != ME_WIDGET_SEPARATOR)
|
|
{
|
|
label = gtk_label_new (_(widget_info[i].label));
|
|
gtk_widget_set_margin_start (label, 3);
|
|
gtk_widget_set_margin_top (label, 3);
|
|
gtk_widget_set_margin_end (label, 3);
|
|
gtk_widget_set_margin_bottom (label, 3);
|
|
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
|
if (widget_info[i].widget_type == ME_WIDGET_TEXT ||
|
|
widget_info[i].widget_type == ME_WIDGET_TREE_GRID)
|
|
gtk_label_set_yalign (GTK_LABEL (label), 0.0);
|
|
gtk_grid_attach (GTK_GRID (grid), label,
|
|
0, widget_info[i].index,
|
|
1, 1);
|
|
gtk_widget_show (label);
|
|
}
|
|
|
|
switch (widget_info[i].widget_type)
|
|
{
|
|
case ME_WIDGET_ENTRY:
|
|
{
|
|
GtkWidget *entry;
|
|
|
|
entry = gtk_entry_new ();
|
|
gtk_widget_set_hexpand(GTK_WIDGET (entry), TRUE);
|
|
gtk_widget_set_margin_end (entry, 5);
|
|
gtk_grid_attach (GTK_GRID (grid), entry,
|
|
1, widget_info[i].index,
|
|
1, 1);
|
|
gtk_widget_show (entry);
|
|
g_hash_table_insert (meta_info->widgets, widget_info[i].id,
|
|
(gpointer) entry);
|
|
}
|
|
break;
|
|
|
|
case ME_WIDGET_TEXT:
|
|
{
|
|
GtkWidget *textview;
|
|
GtkWidget *scrolled_window;
|
|
|
|
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
|
|
gtk_widget_set_hexpand(GTK_WIDGET (scrolled_window), TRUE);
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
|
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
|
|
GTK_SHADOW_IN);
|
|
gtk_widget_set_margin_end (scrolled_window, 5);
|
|
gtk_widget_show (scrolled_window);
|
|
|
|
textview = gtk_text_view_new();
|
|
gtk_container_add (GTK_CONTAINER (scrolled_window), textview);
|
|
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_WORD);
|
|
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (textview), 6);
|
|
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (textview), 6);
|
|
gtk_widget_show (textview);
|
|
gtk_grid_attach (GTK_GRID (grid), scrolled_window,
|
|
1, widget_info[i].index,
|
|
1, 1);
|
|
g_hash_table_insert (meta_info->widgets, widget_info[i].id,
|
|
(gpointer) textview);
|
|
}
|
|
break;
|
|
|
|
case ME_WIDGET_COMBO:
|
|
{
|
|
GtkWidget *combo;
|
|
|
|
combo = gtk_combo_box_text_new ();
|
|
gtk_widget_set_hexpand(GTK_WIDGET (combo), TRUE);
|
|
gtk_widget_set_margin_end (combo, 5);
|
|
gtk_widget_set_can_focus (combo, FALSE);
|
|
gtk_grid_attach (GTK_GRID (grid), combo,
|
|
1, widget_info[i].index,
|
|
1, 1);
|
|
gtk_widget_show (combo);
|
|
g_hash_table_insert (meta_info->widgets, widget_info[i].id,
|
|
(gpointer) combo);
|
|
}
|
|
break;
|
|
|
|
case ME_WIDGET_DATE_BOX:
|
|
{
|
|
GtkWidget *date_box, *date_entry, *button;
|
|
|
|
/* A date_entry and a button in one grid cell using a box as parent */
|
|
|
|
date_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
gtk_widget_set_hexpand(GTK_WIDGET (date_box), TRUE);
|
|
gtk_grid_attach (GTK_GRID (grid), date_box,
|
|
1, widget_info[i].index,
|
|
1, 1);
|
|
gtk_widget_show (date_box);
|
|
|
|
date_entry = gtk_entry_new ();
|
|
gtk_widget_set_hexpand(GTK_WIDGET (date_entry), TRUE);
|
|
gtk_box_pack_start (GTK_BOX (date_box), date_entry, TRUE, TRUE, 0);
|
|
gtk_widget_show (date_entry);
|
|
g_hash_table_insert (meta_info->widgets, widget_info[i].id,
|
|
(gpointer) date_entry);
|
|
|
|
button = gtk_button_new_from_icon_name (widget_info[i].extra_id2,
|
|
GTK_ICON_SIZE_BUTTON);
|
|
gtk_widget_set_size_request (button, 24, 24);
|
|
gtk_widget_set_margin_start (button, 5);
|
|
gtk_widget_set_margin_end (button, 5);
|
|
gtk_widget_set_margin_bottom (button, 1);
|
|
gtk_container_add (GTK_CONTAINER (date_box), button);
|
|
gtk_widget_show (button);
|
|
g_hash_table_insert (meta_args.widgets, widget_info[i].extra_id1,
|
|
(gpointer) button);
|
|
}
|
|
break;
|
|
|
|
case ME_WIDGET_EC_BOX:
|
|
{
|
|
GtkWidget *ec_box, *ec_entry, *ec_combo;
|
|
|
|
/* A box containing an Entry widget and a Combo widget,
|
|
* where the combo widget is limited in size (100).
|
|
* If needed, you can change size manually after creation. */
|
|
|
|
ec_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
gtk_widget_set_hexpand(GTK_WIDGET (ec_box), TRUE);
|
|
gtk_widget_set_margin_end (ec_box, 5);
|
|
gtk_grid_attach (GTK_GRID (grid), ec_box,
|
|
1, widget_info[i].index,
|
|
1, 1);
|
|
gtk_widget_show (ec_box);
|
|
|
|
ec_entry = gtk_entry_new ();
|
|
gtk_widget_set_hexpand(GTK_WIDGET (ec_entry), TRUE);
|
|
gtk_box_pack_start (GTK_BOX (ec_box), ec_entry, TRUE, TRUE, 0);
|
|
gtk_widget_show (ec_entry);
|
|
g_hash_table_insert (meta_info->widgets, widget_info[i].id,
|
|
(gpointer) ec_entry);
|
|
|
|
ec_combo = gtk_combo_box_text_new ();
|
|
gtk_widget_set_margin_start (ec_combo, 5);
|
|
gtk_widget_set_can_focus (ec_combo, FALSE);
|
|
g_object_set (G_OBJECT (ec_combo), "width_request", 100, NULL);
|
|
gtk_box_pack_start (GTK_BOX (ec_box), ec_combo, FALSE, FALSE, 0);
|
|
gtk_widget_show (ec_combo);
|
|
g_hash_table_insert (meta_info->widgets, widget_info[i].extra_id1,
|
|
(gpointer) ec_combo);
|
|
}
|
|
break;
|
|
|
|
case ME_WIDGET_TREE_GRID:
|
|
/* Needs to be handled separately. */
|
|
break;
|
|
|
|
case ME_WIDGET_SEPARATOR:
|
|
{
|
|
GtkWidget *separator;
|
|
|
|
separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
|
|
g_object_set (G_OBJECT (separator), "margin", 8, NULL);
|
|
gtk_widget_show (separator);
|
|
gtk_grid_attach (GTK_GRID (grid), separator,
|
|
0, widget_info[i].index,
|
|
2, 1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
metadata_editor_create_tree_grid (const me_column_info *tree_info,
|
|
gint n_items,
|
|
gint grid_row,
|
|
const me_widget_info *widget_info,
|
|
GtkWidget *grid,
|
|
GtkListStore *store,
|
|
metadata_editor *meta_info)
|
|
{
|
|
/* Creates a GtkBox containing a GtkTreeView and a GtkBox which holds the
|
|
add/remove buttons. */
|
|
|
|
GtkWidget *tree_box, *tree;
|
|
GtkWidget *button_box, *button;
|
|
|
|
tree_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_widget_set_hexpand(GTK_WIDGET (tree_box), TRUE);
|
|
gtk_widget_set_margin_end (tree_box, 5);
|
|
gtk_widget_show (tree_box);
|
|
gtk_grid_attach (GTK_GRID (grid), tree_box,
|
|
1, grid_row,
|
|
1, 1);
|
|
|
|
tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
|
|
gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (tree), FALSE);
|
|
gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (tree), GTK_TREE_VIEW_GRID_LINES_BOTH);
|
|
gtk_box_pack_start (GTK_BOX (tree_box), tree, TRUE, TRUE, 0);
|
|
gtk_widget_show (tree);
|
|
|
|
g_hash_table_insert (meta_info->widgets, widget_info[grid_row].id, (gpointer) tree);
|
|
|
|
for (int i = 0; i < n_items; i++)
|
|
{
|
|
GtkTreeViewColumn *column;
|
|
GtkCellRenderer *render;
|
|
|
|
switch (tree_info[i].renderer_type)
|
|
{
|
|
case ME_RENDER_TEXT:
|
|
render = gtk_cell_renderer_text_new ();
|
|
column = gtk_tree_view_column_new_with_attributes (_(tree_info[i].label),
|
|
render,
|
|
"text", i,
|
|
NULL);
|
|
|
|
break;
|
|
|
|
case ME_RENDER_COMBO:
|
|
render = gtk_cell_renderer_combo_new ();
|
|
column = gtk_tree_view_column_new_with_attributes (_(tree_info[i].label),
|
|
render,
|
|
"text", i,
|
|
NULL);
|
|
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
}
|
|
|
|
gtk_tree_view_column_set_resizable (column, TRUE);
|
|
gtk_tree_view_column_set_spacing (column, 3);
|
|
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
|
|
}
|
|
|
|
button_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
gtk_widget_set_margin_top (button_box, 5);
|
|
gtk_widget_set_margin_bottom (button_box, 5);
|
|
gtk_box_pack_start (GTK_BOX (tree_box), button_box, FALSE, FALSE, 0);
|
|
gtk_widget_show (button_box);
|
|
|
|
button = gtk_button_new_from_icon_name ("list-add", GTK_ICON_SIZE_BUTTON);
|
|
gtk_widget_set_size_request (button, 24, 24);
|
|
gtk_widget_set_margin_end (button, 5);
|
|
gtk_container_add (GTK_CONTAINER (button_box), button);
|
|
gtk_widget_show (button);
|
|
g_hash_table_insert (meta_args.widgets, widget_info[grid_row].extra_id1, (gpointer) button);
|
|
|
|
button = gtk_button_new_from_icon_name ("list-remove", GTK_ICON_SIZE_BUTTON);
|
|
gtk_widget_set_size_request (button, 24, 24);
|
|
gtk_widget_set_margin_start (button, 5);
|
|
gtk_container_add (GTK_CONTAINER (button_box), button);
|
|
gtk_widget_show (button);
|
|
g_hash_table_insert (meta_args.widgets, widget_info[grid_row].extra_id2, (gpointer) button);
|
|
}
|
|
|
|
static gboolean
|
|
metadata_editor_dialog (GimpImage *image,
|
|
GimpMetadata *g_metadata,
|
|
GError **error)
|
|
{
|
|
GExiv2Metadata *metadata;
|
|
GtkWidget *dialog;
|
|
GtkWidget *content_area;
|
|
GtkWidget *metadata_vbox;
|
|
GtkWidget *impex_combo;
|
|
GtkWidget *notebook;
|
|
GtkWidget *box;
|
|
GtkWidget *grid;
|
|
GtkWidget *widget;
|
|
GtkListStore *store;
|
|
gchar *title;
|
|
gchar *name;
|
|
|
|
metadata = GEXIV2_METADATA (g_metadata);
|
|
|
|
meta_args.image = image;
|
|
/* Default filename used for import/export */
|
|
meta_args.filename = g_strconcat (g_get_home_dir (), "/", DEFAULT_TEMPLATE_FILE,
|
|
NULL);
|
|
meta_args.widgets = g_hash_table_new (g_str_hash, g_str_equal);
|
|
meta_args.metadata = metadata;
|
|
|
|
name = gimp_image_get_name (image);
|
|
title = g_strdup_printf (_("Metadata Editor: %s"), 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);
|
|
g_free (title);
|
|
|
|
gtk_widget_set_size_request(dialog, 650, 500);
|
|
|
|
meta_args.dialog = dialog;
|
|
|
|
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
|
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
|
|
GTK_RESPONSE_OK,
|
|
GTK_RESPONSE_CANCEL,
|
|
-1);
|
|
|
|
gimp_window_set_transient (GTK_WINDOW (dialog));
|
|
|
|
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
|
|
|
|
metadata_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
|
gtk_box_pack_start (GTK_BOX (content_area), metadata_vbox, TRUE, TRUE, 0);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (metadata_vbox), 12);
|
|
gtk_box_set_spacing (GTK_BOX (metadata_vbox), 6);
|
|
gtk_widget_show (metadata_vbox);
|
|
|
|
notebook = gtk_notebook_new ();
|
|
gtk_box_pack_start (GTK_BOX (metadata_vbox), notebook, TRUE, TRUE, 0);
|
|
|
|
/* Description tab */
|
|
|
|
grid = metadata_editor_create_page_grid (notebook, _("Description"));
|
|
|
|
metadata_editor_create_widgets (description_tab_data, n_description_tab_data, grid, &meta_args);
|
|
|
|
/* IPTC tab */
|
|
|
|
grid = metadata_editor_create_page_grid (notebook, _("IPTC"));
|
|
|
|
metadata_editor_create_widgets (iptc_tab_data, n_iptc_tab_data, grid, &meta_args);
|
|
|
|
/* IPTC Extension tab */
|
|
|
|
grid = metadata_editor_create_page_grid (notebook, _("IPTC Extension"));
|
|
|
|
metadata_editor_create_widgets (iptc_extension_tab_data, n_iptc_extension_tab_data, grid, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_location_shown_info,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_LOCATION_SHOWN].id, ==, "Xmp.iptcExt.LocationShown");
|
|
metadata_editor_create_tree_grid (location_shown_info, n_location_shown_info,
|
|
C_LOCATION_SHOWN, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_featured_organization_info,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_FEATURED_ORG].id, ==, "Xmp.iptcExt.OrganisationInImageName");
|
|
metadata_editor_create_tree_grid (featured_organization_info, n_featured_organization_info,
|
|
C_FEATURED_ORG, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_featured_organization_code_info,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_FEATURED_ORG_CODE].id, ==, "Xmp.iptcExt.OrganisationInImageCode");
|
|
metadata_editor_create_tree_grid (featured_organization_code_info, n_featured_organization_code_info,
|
|
C_FEATURED_ORG_CODE, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_artwork_object_info,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_ART_OBJECT].id, ==, "Xmp.iptcExt.ArtworkOrObject");
|
|
metadata_editor_create_tree_grid (artwork_object_info, n_artwork_object_info,
|
|
C_ART_OBJECT, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_model_release_id_info,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_MODEL_RELEASE_ID].id, ==, "Xmp.plus.ModelReleaseID");
|
|
metadata_editor_create_tree_grid (model_release_id_info, n_model_release_id_info,
|
|
C_MODEL_RELEASE_ID, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_registry_entry_info,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_REGISTRY_ENTRY].id, ==, "Xmp.iptcExt.RegistryId");
|
|
metadata_editor_create_tree_grid (registry_entry_info, n_registry_entry_info,
|
|
C_REGISTRY_ENTRY, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_image_creator_info,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_IMAGE_CREATOR].id, ==, "Xmp.plus.ImageCreator");
|
|
metadata_editor_create_tree_grid (image_creator_info, n_image_creator_info,
|
|
C_IMAGE_CREATOR, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_copyright_owner_info,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_COPYRIGHT_OWNER].id, ==, "Xmp.plus.CopyrightOwner");
|
|
metadata_editor_create_tree_grid (copyright_owner_info, n_copyright_owner_info,
|
|
C_COPYRIGHT_OWNER, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_licensor_info,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_LICENSOR].id, ==, "Xmp.plus.Licensor");
|
|
metadata_editor_create_tree_grid (licensor_info, n_licensor_info,
|
|
C_LICENSOR, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
store = gtk_list_store_new (n_property_release_id_info,
|
|
G_TYPE_STRING);
|
|
|
|
g_assert_cmpstr (iptc_extension_tab_data[C_PROPERTY_RELEASE_ID].id, ==, "Xmp.plus.PropertyReleaseID");
|
|
metadata_editor_create_tree_grid (property_release_id_info, n_property_release_id_info,
|
|
C_PROPERTY_RELEASE_ID, iptc_extension_tab_data,
|
|
grid, store, &meta_args);
|
|
|
|
/* Categories tab */
|
|
|
|
grid = metadata_editor_create_page_grid (notebook, _("Categories"));
|
|
|
|
metadata_editor_create_widgets (categories_labels, n_categories_labels, grid, &meta_args);
|
|
|
|
/* GPS tab */
|
|
|
|
grid = metadata_editor_create_page_grid (notebook, _("GPS"));
|
|
|
|
metadata_editor_create_widgets (gps_labels, n_gps_labels, grid, &meta_args);
|
|
|
|
/* Update GPSAltitudeSystem combo width */
|
|
|
|
widget = metadata_editor_get_widget (&meta_args, "GPSAltitudeSystem");
|
|
g_object_set (G_OBJECT (widget), "width_request", 60, NULL);
|
|
|
|
/* DICOM tab */
|
|
|
|
grid = metadata_editor_create_page_grid (notebook, _("DICOM"));
|
|
|
|
metadata_editor_create_widgets (dicom_info_labels, n_dicom_info_labels, grid, &meta_args);
|
|
|
|
/* Show notebook */
|
|
|
|
gtk_widget_show (notebook);
|
|
|
|
/* Import / Export options box */
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
gtk_box_pack_start (GTK_BOX (metadata_vbox), box, FALSE, TRUE, 0);
|
|
gtk_widget_show (box);
|
|
|
|
impex_combo = gtk_combo_box_text_new ();
|
|
g_object_set (G_OBJECT (impex_combo), "width_request", 160, NULL);
|
|
gtk_box_pack_start (GTK_BOX (box), impex_combo, FALSE, FALSE, 6);
|
|
gtk_widget_show (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);
|
|
|
|
/* Add signals, combobox choices, and actual metadata */
|
|
|
|
metadata_dialog_editor_set_metadata (metadata, &meta_args);
|
|
|
|
if (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK)
|
|
{
|
|
metadata_editor_write_callback (dialog, &meta_args, image);
|
|
}
|
|
|
|
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_try_has_tag (metadata, (gchar *) &tag, NULL))
|
|
{
|
|
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);
|
|
_datarow = (gchar **) tagdata[row-1];
|
|
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_try_get_tag_string (metadata, (gchar *) &tag, NULL);
|
|
|
|
g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "get_tags tag: %s, value: %s", (gchar *) &tag, value);
|
|
|
|
if (_datarow && value)
|
|
_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)
|
|
{
|
|
GtkWidget *calendar_dialog;
|
|
GtkWidget *calendar_content_area;
|
|
GtkWidget *calendar_vbox;
|
|
GtkWidget *calendar;
|
|
const gchar *date_text;
|
|
GDateTime *current_datetime;
|
|
guint year, month, day;
|
|
|
|
date_text = gtk_entry_get_text (GTK_ENTRY (entry_widget));
|
|
if (date_text && date_text[0] != '\0')
|
|
{
|
|
sscanf (date_text, "%u-%u-%u;", &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 (_("Choose 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);
|
|
gimp_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 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
|
gtk_container_set_border_width (GTK_CONTAINER (calendar_vbox), 6);
|
|
gtk_box_pack_start (GTK_BOX (calendar_content_area), calendar_vbox, TRUE, TRUE, 0);
|
|
|
|
calendar = gtk_calendar_new ();
|
|
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);
|
|
gtk_widget_show (calendar);
|
|
|
|
gtk_container_add (GTK_CONTAINER (calendar_vbox), calendar);
|
|
gtk_widget_show (calendar_vbox);
|
|
|
|
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, "%u-%02u-%02uT00:00:00+00:00", year, month+1, day);
|
|
gtk_entry_set_text (GTK_ENTRY (entry_widget), date);
|
|
}
|
|
|
|
gtk_widget_destroy (calendar_dialog);
|
|
}
|
|
|
|
/* ============================================================================
|
|
* ==[ SPECIAL TAGS HANDLERS ]=================================================
|
|
* ============================================================================
|
|
*/
|
|
|
|
gboolean
|
|
hasImageSupplierTagData (metadata_editor *meta_info)
|
|
{
|
|
gint loop;
|
|
|
|
for (loop = 0; loop < n_imageSupplierInfoTags; loop++)
|
|
{
|
|
GtkWidget *object;
|
|
const gchar *text;
|
|
|
|
object = metadata_editor_get_widget (meta_info, imageSupplierInfoTags[loop].id);
|
|
|
|
if (imageSupplierInfoTags[loop].mode == MODE_SINGLE)
|
|
{
|
|
text = gtk_entry_get_text (GTK_ENTRY (object));
|
|
|
|
if (text && *text)
|
|
return TRUE;
|
|
}
|
|
else if (imageSupplierInfoTags[loop].mode == MODE_MULTI)
|
|
{
|
|
text = gtk_entry_get_text (GTK_ENTRY (object));
|
|
|
|
if (text && *text)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
hasLocationCreationTagData (metadata_editor *meta_info)
|
|
{
|
|
gint loop;
|
|
|
|
for (loop = 0; loop < n_locationCreationInfoTags; loop++)
|
|
{
|
|
GtkWidget *widget;
|
|
const gchar *text;
|
|
|
|
widget = metadata_editor_get_widget (meta_info, locationCreationInfoTags[loop].id);
|
|
|
|
if (locationCreationInfoTags[loop].mode == MODE_SINGLE)
|
|
{
|
|
text = gtk_entry_get_text (GTK_ENTRY (widget));
|
|
|
|
if (text && *text)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
hasModelReleaseTagData (metadata_editor *meta_info)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
hasPropertyReleaseTagData (metadata_editor *meta_info)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
gboolean
|
|
hasCreatorTagData (metadata_editor *meta_info)
|
|
{
|
|
gboolean has_data = FALSE;
|
|
gint loop;
|
|
|
|
for (loop = 0; loop < n_creatorContactInfoTags; loop++)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
widget = metadata_editor_get_widget (meta_info, creatorContactInfoTags[loop].id);
|
|
|
|
if (GTK_IS_ENTRY (widget))
|
|
{
|
|
const gchar *text = gtk_entry_get_text (GTK_ENTRY (widget));
|
|
|
|
if (text && *text)
|
|
has_data = TRUE;
|
|
}
|
|
else if (GTK_IS_TEXT_VIEW (widget))
|
|
{
|
|
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
|
|
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)
|
|
{
|
|
metadata_editor *meta_info = data;
|
|
GtkWidget *list_widget;
|
|
GtkListStore *liststore;
|
|
GtkTreeIter iter;
|
|
GtkTreeModel *treemodel;
|
|
GtkTreeSelection *selection;
|
|
GtkTreePath *path;
|
|
|
|
list_widget = metadata_editor_get_widget (meta_info, 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)
|
|
{
|
|
metadata_editor *meta_info = data;
|
|
GtkWidget *list_widget;
|
|
GtkListStore *liststore;
|
|
GtkTreeIter iter;
|
|
|
|
list_widget = metadata_editor_get_widget (meta_info, 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,
|
|
metadata_editor *meta_info)
|
|
{
|
|
GtkWidget *combo_widget;
|
|
GtkWidget *entry_widget;
|
|
GtkWidget *button_widget;
|
|
gint width, height;
|
|
gchar *value;
|
|
gint i;
|
|
|
|
gint32 numele = n_default_metadata_tags;
|
|
|
|
/* Setup Buttons */
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_licensor_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (licensor_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_licensor_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (licensor_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_copyright_own_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (copyright_own_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_copyright_own_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (copyright_own_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_image_creator_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (image_creator_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_image_creator_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (image_creator_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_reg_entry_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (reg_entry_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_reg_entry_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (reg_entry_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_artwork_object_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (artwork_object_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_artwork_object_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (artwork_object_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_feat_org_code_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (feat_org_code_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_feat_org_code_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (feat_org_code_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_feat_org_name_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (feat_org_name_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_feat_org_name_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (feat_org_name_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_shown_location_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (shown_location_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_shown_location_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (shown_location_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_model_rel_id_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (model_release_id_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_model_rel_id_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (model_release_id_remove_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "add_prop_rel_id_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (property_release_id_add_callback),
|
|
meta_info);
|
|
|
|
button_widget = metadata_editor_get_widget (meta_info, "rem_prop_rel_id_button");
|
|
g_signal_connect (G_OBJECT (button_widget), "clicked",
|
|
G_CALLBACK (property_release_id_remove_callback),
|
|
meta_info);
|
|
|
|
/* Setup Comboboxes */
|
|
combo_widget = metadata_editor_get_widget (meta_info, "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 = metadata_editor_get_widget (meta_info, "Xmp.xmpRights.Marked");
|
|
for (i = 0; i < n_marked; 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 = metadata_editor_get_widget (meta_info, "Xmp.photoshop.Urgency");
|
|
for (i = 0; i < n_urgency; 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 = metadata_editor_get_widget (meta_info, "Xmp.plus.MinorModelAgeDisclosure");
|
|
for (i = 0; i < n_minormodelagedisclosure; 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 = metadata_editor_get_widget (meta_info, "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 = metadata_editor_get_widget (meta_info, "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 = metadata_editor_get_widget (meta_info, "Xmp.plus.PropertyReleaseStatus");
|
|
for (i = 0; i < n_propertyreleasestatus; 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 = metadata_editor_get_widget (meta_info, "Xmp.DICOM.PatientSex");
|
|
for (i = 0; i < n_dicom; 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 = metadata_editor_get_widget (meta_info, "Exif.GPSInfo.GPSLatitudeRef");
|
|
for (i = 0; i < n_gpslatref; 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 = metadata_editor_get_widget (meta_info, "Exif.GPSInfo.GPSLongitudeRef");
|
|
for (i = 0; i < n_gpslngref; 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 = metadata_editor_get_widget (meta_info, "Exif.GPSInfo.GPSAltitudeRef");
|
|
for (i = 0; i < n_gpsaltref; 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 = metadata_editor_get_widget (meta_info, "GPSAltitudeSystem");
|
|
for (i = 0; i < n_gpsaltsys; 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),
|
|
meta_info);
|
|
|
|
/* Set up text view heights */
|
|
|
|
/* Set up lists */
|
|
for (i = 0; i < n_imageSupplierInfoTags; i++)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
widget = metadata_editor_get_widget (meta_info,
|
|
imageSupplierInfoTags[i].id);
|
|
|
|
value = gexiv2_metadata_try_get_tag_interpreted_string (metadata,
|
|
imageSupplierInfoTags[i].tag,
|
|
NULL);
|
|
|
|
if (value)
|
|
{
|
|
gchar *value_utf;
|
|
|
|
value_utf = clean_xmp_string (value);
|
|
g_free (value);
|
|
|
|
if (imageSupplierInfoTags[i].mode == MODE_SINGLE)
|
|
{
|
|
gtk_entry_set_text (GTK_ENTRY (widget), value_utf);
|
|
}
|
|
else if (imageSupplierInfoTags[i].mode == MODE_MULTI)
|
|
{
|
|
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 < n_locationCreationInfoTags; i++)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
widget = metadata_editor_get_widget (meta_info,
|
|
locationCreationInfoTags[i].id);
|
|
|
|
value = gexiv2_metadata_try_get_tag_interpreted_string (metadata,
|
|
locationCreationInfoTags[i].tag,
|
|
NULL);
|
|
|
|
if (value)
|
|
{
|
|
gchar *value_utf;
|
|
|
|
value_utf = clean_xmp_string (value);
|
|
g_free (value);
|
|
|
|
if (locationCreationInfoTags[i].mode == MODE_SINGLE)
|
|
{
|
|
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 = metadata_editor_get_widget (meta_info, default_metadata_tags[i].tag);
|
|
|
|
if (! strcmp ("Exif.GPSInfo.GPSLongitude",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
gdouble gps_value;
|
|
gchar *str;
|
|
|
|
if (gexiv2_metadata_try_get_gps_longitude (metadata, &gps_value, NULL))
|
|
{
|
|
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_try_get_gps_latitude (metadata, &gps_value, NULL))
|
|
{
|
|
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_try_get_gps_altitude (metadata, &gps_value, NULL))
|
|
{
|
|
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_try_get_tag_multiple (metadata,
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
|
|
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;
|
|
|
|
if (equivalent_metadata_tags[index].exif_tag_index > -1)
|
|
{
|
|
gint32 i_exif = equivalent_metadata_tags[index].exif_tag_index;
|
|
const gchar *exif_tag_str = exif_equivalent_tags[i_exif].tag;
|
|
gchar *exif_value = NULL;
|
|
|
|
exif_value = gexiv2_metadata_try_get_tag_interpreted_string (metadata,
|
|
exif_tag_str,
|
|
NULL);
|
|
|
|
if (exif_value)
|
|
{
|
|
if (! value)
|
|
{
|
|
value = exif_value;
|
|
exif_value = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (g_strcmp0 (value, exif_value))
|
|
{
|
|
g_printerr ("Value of tag %s: '%s' is not the same as %s: '%s'. "
|
|
"Ignoring value of %s.\n",
|
|
default_metadata_tags[equivalent_metadata_tags[index].default_tag_index].tag,
|
|
value, exif_tag_str, exif_value, exif_tag_str);
|
|
}
|
|
}
|
|
}
|
|
g_free (exif_value);
|
|
}
|
|
|
|
/* 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_try_get_tag_multiple (metadata,
|
|
equivalent_metadata_tags[index].tag,
|
|
NULL);
|
|
|
|
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 ((const gchar * const *) values, equiv_values[evi]))
|
|
{
|
|
gchar *tmpvalue;
|
|
|
|
tmpvalue = value;
|
|
value = g_strconcat (value, "\n", equiv_values[evi], NULL);
|
|
g_free (tmpvalue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
g_strfreev (equiv_values);
|
|
}
|
|
}
|
|
g_strfreev (values);
|
|
}
|
|
else
|
|
{
|
|
value = gexiv2_metadata_try_get_tag_interpreted_string (metadata,
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
|
|
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 == SPECIAL_PROCESSING_DATE_CREATED)
|
|
{
|
|
gchar *date_value = NULL;
|
|
gchar *date_time_value = NULL;
|
|
|
|
/* XMP: Check if Xmp.photoshop.DateCreated has the same value as
|
|
IPTC: Iptc.Application2.DateCreated, and
|
|
Iptc.Application2.TimeCreated combined.
|
|
If empty, this can be filled from:
|
|
Exif: DateTimeOriginal, OffsetTimeOriginal
|
|
*/
|
|
date_value = gexiv2_metadata_try_get_tag_string (metadata,
|
|
"Iptc.Application2.DateCreated",
|
|
NULL);
|
|
if (date_value)
|
|
{
|
|
gchar *time_value = NULL;
|
|
|
|
time_value = gexiv2_metadata_try_get_tag_string (metadata,
|
|
"Iptc.Application2.TimeCreated",
|
|
NULL);
|
|
if (time_value)
|
|
{
|
|
date_time_value = g_strconcat (date_value, "T", time_value, NULL);
|
|
g_free (time_value);
|
|
|
|
if (! value)
|
|
{
|
|
/* Copy Xmp value from IPTC values*/
|
|
value = date_time_value;
|
|
date_time_value = NULL;
|
|
}
|
|
else if (strcmp (value, date_time_value))
|
|
{
|
|
g_printerr ("Xmp.Photoshop.DateCreated %s is not the same as "
|
|
"the combined IPTC DateCreated and TimeCreated "
|
|
"values: %s. The IPTC values will be ignored.\n",
|
|
value, date_time_value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (! value)
|
|
{
|
|
value = g_strconcat (date_value, "T00:00:00+00:00", NULL);
|
|
}
|
|
else
|
|
{
|
|
g_printerr ("Missing IPTC TimeCreated tag. We won't "
|
|
"compare the IPTC DateCreated value"
|
|
"with Xmp.Photoshop.DateCreated.\n");
|
|
}
|
|
}
|
|
}
|
|
else if (! value)
|
|
{
|
|
/* Set initial value from Exif */
|
|
date_value = gexiv2_metadata_try_get_tag_string (metadata,
|
|
"Exif.Photo.DateTimeOriginal",
|
|
NULL);
|
|
if (date_value)
|
|
{
|
|
gchar **date_time_split = NULL;
|
|
|
|
/* Exif has space as separator between date and time,
|
|
and no timezone, which is a separate tag. */
|
|
date_time_split = g_strsplit (date_value, " ", 2);
|
|
|
|
if (date_time_split[0] != NULL)
|
|
{
|
|
gchar *time_zone = NULL;
|
|
|
|
/* Exif uses ':' as date delimiter instead of '-' */
|
|
g_strdelimit (date_time_split[0], ":", '-');
|
|
|
|
if (date_time_split[1] != NULL)
|
|
{
|
|
date_time_value = g_strconcat (date_time_split[0],
|
|
"T", date_time_split[1],
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
date_time_value = g_strconcat (date_time_split[0],
|
|
"T00:00:00", NULL);
|
|
}
|
|
|
|
time_zone = gexiv2_metadata_try_get_tag_string (metadata,
|
|
"Exif.Photo.OffsetTimeOriginal",
|
|
NULL);
|
|
if (time_zone)
|
|
{
|
|
value = g_strconcat (date_time_value, time_zone, NULL);
|
|
}
|
|
else
|
|
{
|
|
value = g_strconcat (date_time_value, "+00:00", NULL);
|
|
}
|
|
g_free (time_zone);
|
|
}
|
|
g_strfreev (date_time_split);
|
|
}
|
|
}
|
|
g_free (date_value);
|
|
g_free (date_time_value);
|
|
}
|
|
else if (index > -1)
|
|
{
|
|
gchar **values;
|
|
|
|
if (equivalent_metadata_tags[index].exif_tag_index > -1)
|
|
{
|
|
gint32 i_exif = equivalent_metadata_tags[index].exif_tag_index;
|
|
const gchar *exif_tag_str = exif_equivalent_tags[i_exif].tag;
|
|
gchar *exif_value = NULL;
|
|
|
|
exif_value = gexiv2_metadata_try_get_tag_interpreted_string (metadata,
|
|
exif_tag_str,
|
|
NULL);
|
|
|
|
if (exif_value)
|
|
{
|
|
|
|
if (! value)
|
|
{
|
|
value = exif_value;
|
|
exif_value = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (g_strcmp0 (value, exif_value))
|
|
{
|
|
g_printerr ("Value of tag %s: '%s' is not the same as %s: '%s'. "
|
|
"Ignoring value of %s.\n",
|
|
default_metadata_tags[equivalent_metadata_tags[index].default_tag_index].tag,
|
|
value, exif_tag_str, exif_value, exif_tag_str);
|
|
}
|
|
}
|
|
}
|
|
g_free (exif_value);
|
|
}
|
|
|
|
/* 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_try_get_tag_multiple (metadata,
|
|
equivalent_metadata_tags[index].tag,
|
|
NULL);
|
|
|
|
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 (equivalent_metadata_tags[index].mode == MODE_MULTI)
|
|
{
|
|
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 (equivalent_metadata_tags[index].mode == MODE_MULTI)
|
|
{
|
|
g_string_prepend (str, "\n");
|
|
}
|
|
else
|
|
{
|
|
g_string_prepend (str, ", ");
|
|
}
|
|
g_string_prepend (str, value);
|
|
g_free (value);
|
|
}
|
|
value = g_string_free (str, FALSE);
|
|
}
|
|
g_strfreev (values);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (default_metadata_tags[i].mode == MODE_LIST)
|
|
{
|
|
/* 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 < n_phone_types; 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 < n_phone_types; 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 (default_metadata_tags[i].mode == MODE_SINGLE)
|
|
{
|
|
gtk_entry_set_text (GTK_ENTRY (widget), value);
|
|
}
|
|
else if (default_metadata_tags[i].mode == MODE_MULTI)
|
|
{
|
|
GtkTextBuffer *buffer;
|
|
|
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
|
gtk_text_buffer_set_text (buffer, value, -1);
|
|
}
|
|
else if (default_metadata_tags[i].mode == MODE_COMBO)
|
|
{
|
|
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 < n_propertyreleasestatus; 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 < n_creatorContactInfoTags; i++)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
widget = metadata_editor_get_widget (meta_info, creatorContactInfoTags[i].id);
|
|
|
|
value = gexiv2_metadata_try_get_tag_interpreted_string (metadata,
|
|
creatorContactInfoTags[i].tag,
|
|
NULL);
|
|
|
|
if (value)
|
|
{
|
|
gchar *value_utf;
|
|
|
|
value_utf = clean_xmp_string (value);
|
|
g_free (value);
|
|
|
|
if (creatorContactInfoTags[i].mode == MODE_SINGLE)
|
|
{
|
|
gtk_entry_set_text (GTK_ENTRY (widget), value_utf);
|
|
}
|
|
else if (creatorContactInfoTags[i].mode == MODE_MULTI)
|
|
{
|
|
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 = metadata_editor_get_widget (meta_info, "create_date_button");
|
|
g_signal_connect (entry_widget, "clicked",
|
|
G_CALLBACK (on_create_date_button_clicked),
|
|
metadata_editor_get_widget (meta_info,
|
|
"Xmp.photoshop.DateCreated"));
|
|
|
|
/* Set patient dob date */
|
|
entry_widget = metadata_editor_get_widget (meta_info, "dob_date_button");
|
|
g_signal_connect (entry_widget, "clicked",
|
|
G_CALLBACK (on_patient_dob_date_button_clicked),
|
|
metadata_editor_get_widget (meta_info,
|
|
"Xmp.DICOM.PatientDOB"));
|
|
|
|
/* Set study date */
|
|
entry_widget = metadata_editor_get_widget (meta_info, "study_date_button");
|
|
g_signal_connect (entry_widget, "clicked",
|
|
G_CALLBACK (on_study_date_button_clicked),
|
|
metadata_editor_get_widget (meta_info,
|
|
"Xmp.DICOM.StudyDateTime"));
|
|
|
|
/* Set series date */
|
|
entry_widget = metadata_editor_get_widget (meta_info, "series_date_button");
|
|
g_signal_connect (entry_widget, "clicked",
|
|
G_CALLBACK (on_series_date_button_clicked),
|
|
metadata_editor_get_widget (meta_info,
|
|
"Xmp.DICOM.SeriesDateTime"));
|
|
}
|
|
|
|
|
|
/* ============================================================================
|
|
* ==[ WRITE METADATA ]========================================================
|
|
* ============================================================================
|
|
*/
|
|
|
|
static void
|
|
set_tag_failed (const gchar *tag, gchar *error_message)
|
|
{
|
|
g_log ("", G_LOG_LEVEL_MESSAGE,
|
|
_("Failed to set metadata tag %s: %s"), tag, error_message);
|
|
}
|
|
|
|
static void
|
|
set_tag_string (GimpMetadata *metadata,
|
|
const gchar *name,
|
|
const gchar *value,
|
|
gboolean clear_tag)
|
|
{
|
|
GError *error = NULL;
|
|
|
|
if (! metadata || ! name) return;
|
|
|
|
if (clear_tag)
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (metadata), name, NULL);
|
|
|
|
if (! value) return;
|
|
|
|
if (! gexiv2_metadata_try_set_tag_string (GEXIV2_METADATA (metadata),
|
|
name, value, &error))
|
|
{
|
|
set_tag_failed (name, error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
}
|
|
|
|
static gchar *
|
|
get_phonetype (gchar *cur_value)
|
|
{
|
|
gchar *phone_type_value = NULL;
|
|
gint types;
|
|
|
|
if (cur_value != NULL)
|
|
{
|
|
for (types = 0; types < n_phone_types; 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 (metadata_editor *meta_info,
|
|
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 = metadata_editor_get_widget (meta_info, 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, TRUE);
|
|
g_string_free (data, TRUE);
|
|
}
|
|
|
|
static void
|
|
write_metadata_tag_multiple (metadata_editor *meta_info, 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_try_clear_tag (GEXIV2_METADATA (metadata), header_tag, NULL);
|
|
|
|
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_try_clear_tag (GEXIV2_METADATA (metadata), temp_tag, NULL);
|
|
}
|
|
}
|
|
|
|
list_widget = metadata_editor_get_widget (meta_info, 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_try_set_xmp_tag_struct (GEXIV2_METADATA (metadata),
|
|
header_tag,
|
|
GEXIV2_STRUCTURE_XA_BAG,
|
|
NULL);
|
|
|
|
/* 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, TRUE);
|
|
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);
|
|
|
|
set_tag_string (metadata, tag, lng_lat, FALSE);
|
|
}
|
|
else
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (metadata), tag, NULL);
|
|
g_log (ME_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Removed tag %s (no value).", tag);
|
|
}
|
|
}
|
|
|
|
void
|
|
metadata_editor_write_callback (GtkWidget *dialog,
|
|
metadata_editor *meta_info,
|
|
GimpImage *image)
|
|
{
|
|
GimpMetadata *g_metadata;
|
|
gint max_elements;
|
|
gint i = 0;
|
|
|
|
g_metadata = gimp_image_get_metadata (image);
|
|
|
|
gimp_metadata_add_xmp_history (g_metadata, "metadata");
|
|
|
|
write_metadata_tag (meta_info, g_metadata,
|
|
"Xmp.iptcExt.OrganisationInImageName",
|
|
COL_ORG_IMG_NAME);
|
|
|
|
write_metadata_tag (meta_info, g_metadata,
|
|
"Xmp.iptcExt.OrganisationInImageCode",
|
|
COL_ORG_IMG_CODE);
|
|
|
|
write_metadata_tag (meta_info, g_metadata,
|
|
"Xmp.plus.ModelReleaseID",
|
|
COL_MOD_REL_ID);
|
|
|
|
write_metadata_tag (meta_info, g_metadata,
|
|
"Xmp.plus.PropertyReleaseID",
|
|
COL_PROP_REL_ID);
|
|
|
|
write_metadata_tag_multiple (meta_info, g_metadata, GEXIV2_STRUCTURE_XA_BAG,
|
|
"Xmp.iptcExt.LocationShown",
|
|
n_locationshown, locationshown_alternative, NULL);
|
|
|
|
write_metadata_tag_multiple (meta_info, g_metadata, GEXIV2_STRUCTURE_XA_BAG,
|
|
"Xmp.iptcExt.ArtworkOrObject",
|
|
n_artworkorobject, artworkorobject_alternative, NULL);
|
|
|
|
write_metadata_tag_multiple (meta_info, g_metadata, GEXIV2_STRUCTURE_XA_BAG,
|
|
"Xmp.iptcExt.RegistryId",
|
|
n_registryid, registryid_alternative, NULL);
|
|
|
|
write_metadata_tag_multiple (meta_info, g_metadata, GEXIV2_STRUCTURE_XA_SEQ,
|
|
"Xmp.plus.ImageCreator",
|
|
n_imagecreator, imagecreator, NULL);
|
|
|
|
write_metadata_tag_multiple (meta_info, g_metadata, GEXIV2_STRUCTURE_XA_SEQ,
|
|
"Xmp.plus.CopyrightOwner",
|
|
n_copyrightowner, copyrightowner, NULL);
|
|
|
|
write_metadata_tag_multiple (meta_info, g_metadata, GEXIV2_STRUCTURE_XA_SEQ,
|
|
"Xmp.plus.Licensor",
|
|
n_licensor, licensor,
|
|
licensor_special_handling);
|
|
|
|
/* DO CREATOR TAGS */
|
|
|
|
if (hasCreatorTagData (meta_info))
|
|
{
|
|
for (i = 0; i < n_creatorContactInfoTags; i++)
|
|
{
|
|
GtkWidget *widget = metadata_editor_get_widget (meta_info,
|
|
creatorContactInfoTags[i].id);
|
|
|
|
if (creatorContactInfoTags[i].mode == MODE_SINGLE)
|
|
{
|
|
GtkEntry *entry = GTK_ENTRY (widget);
|
|
|
|
set_tag_string (g_metadata, creatorContactInfoTags[i].tag,
|
|
gtk_entry_get_text (entry), FALSE);
|
|
}
|
|
else if (creatorContactInfoTags[i].mode == MODE_MULTI)
|
|
{
|
|
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
|
|
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);
|
|
|
|
set_tag_string (g_metadata, creatorContactInfoTags[i].tag,
|
|
text, FALSE);
|
|
|
|
g_free (text);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* DO SINGLE, MULTI AND COMBO TAGS */
|
|
|
|
else
|
|
{
|
|
for (i = 0; i < n_creatorContactInfoTags; i++)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
creatorContactInfoTags[i].tag,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
max_elements = n_default_metadata_tags;
|
|
|
|
for (i = 0; i < max_elements; i++)
|
|
{
|
|
GtkWidget *widget = metadata_editor_get_widget (meta_info,
|
|
default_metadata_tags[i].tag);
|
|
|
|
/* SINGLE TAGS */
|
|
|
|
if (default_metadata_tags[i].mode == MODE_SINGLE)
|
|
{
|
|
GtkEntry *entry = GTK_ENTRY (widget);
|
|
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 = metadata_editor_get_widget (meta_info,
|
|
"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);
|
|
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
alt_str, FALSE);
|
|
}
|
|
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_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
gexiv2_metadata_try_set_xmp_tag_struct (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
GEXIV2_STRUCTURE_XA_NONE,
|
|
NULL);
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
text_value, FALSE);
|
|
}
|
|
else
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
text_value, FALSE);
|
|
}
|
|
|
|
index = default_metadata_tags[i].other_tag_index;
|
|
if (index == SPECIAL_PROCESSING_DATE_CREATED)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
"Iptc.Application2.DateCreated",
|
|
NULL);
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
"Iptc.Application2.TimeCreated",
|
|
NULL);
|
|
if (text_value)
|
|
{
|
|
gchar **date_time_split = NULL;
|
|
|
|
date_time_split = g_strsplit (text_value, "T", 2);
|
|
if (date_time_split[0] != NULL)
|
|
{
|
|
/* We can't use : as date delimiter for IPTC */
|
|
g_strdelimit (date_time_split[0], ":/.", '-');
|
|
|
|
set_tag_string (g_metadata, "Iptc.Application2.DateCreated",
|
|
date_time_split[0], FALSE);
|
|
|
|
if (date_time_split[1] != NULL)
|
|
{
|
|
set_tag_string (g_metadata, "Iptc.Application2.TimeCreated",
|
|
date_time_split[1], FALSE);
|
|
}
|
|
else
|
|
{
|
|
set_tag_string (g_metadata, "Iptc.Application2.TimeCreated",
|
|
"00:00:00+00:00", FALSE);
|
|
}
|
|
}
|
|
g_strfreev (date_time_split);
|
|
}
|
|
}
|
|
else if (index > -1)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
equivalent_metadata_tags[index].tag,
|
|
NULL);
|
|
if (*text_value)
|
|
set_tag_string (g_metadata, equivalent_metadata_tags[index].tag,
|
|
text_value, FALSE);
|
|
|
|
if (equivalent_metadata_tags[index].exif_tag_index > -1)
|
|
{
|
|
gint i_exif = equivalent_metadata_tags[index].exif_tag_index;
|
|
const gchar *exif_tag_str = exif_equivalent_tags[i_exif].tag;
|
|
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
exif_tag_str,
|
|
NULL);
|
|
if (*text_value)
|
|
set_tag_string (g_metadata, exif_tag_str,
|
|
text_value, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* MULTI TAGS */
|
|
|
|
else if (default_metadata_tags[i].mode == MODE_MULTI)
|
|
{
|
|
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
|
|
GtkTextBuffer *buffer;
|
|
GtkTextIter start;
|
|
GtkTextIter end;
|
|
gchar *text;
|
|
gint index;
|
|
GError *error = NULL;
|
|
|
|
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_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
|
|
if (text && *text)
|
|
{
|
|
if (default_metadata_tags[i].xmp_type == GIMP_XMP_TEXT ||
|
|
default_metadata_tags[i].xmp_type == GIMP_XMP_NONE)
|
|
{
|
|
gexiv2_metadata_try_set_xmp_tag_struct (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
GEXIV2_STRUCTURE_XA_NONE,
|
|
NULL);
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
text, FALSE);
|
|
}
|
|
else
|
|
{
|
|
gchar **multi;
|
|
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
|
|
/* We have one value per line. */
|
|
multi = g_strsplit (text, "\n", 0);
|
|
|
|
if (! gexiv2_metadata_try_set_tag_multiple (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
(const gchar **) multi,
|
|
&error))
|
|
{
|
|
set_tag_failed (default_metadata_tags[i].tag, error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
g_strfreev (multi);
|
|
}
|
|
}
|
|
|
|
index = default_metadata_tags[i].other_tag_index;
|
|
if (index > -1)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
equivalent_metadata_tags[index].tag,
|
|
NULL);
|
|
|
|
if (text && *text)
|
|
{
|
|
if (equivalent_metadata_tags[index].mode == MODE_MULTI)
|
|
{
|
|
gchar **multi;
|
|
|
|
multi = g_strsplit (text, "\n", 0);
|
|
|
|
if (! gexiv2_metadata_try_set_tag_multiple (GEXIV2_METADATA (g_metadata),
|
|
equivalent_metadata_tags[index].tag,
|
|
(const gchar **) multi,
|
|
&error))
|
|
{
|
|
set_tag_failed (equivalent_metadata_tags[index].tag, error->message);
|
|
g_clear_error (&error);
|
|
}
|
|
|
|
g_strfreev (multi);
|
|
}
|
|
else if (equivalent_metadata_tags[index].mode == MODE_SINGLE)
|
|
{
|
|
/* Convert from multiline to single line: keep the \n and just add the whole text. */
|
|
set_tag_string (g_metadata, equivalent_metadata_tags[index].tag,
|
|
text, FALSE);
|
|
}
|
|
else
|
|
{
|
|
g_warning ("Copying from multiline tag %s to tag %s not implemented!",
|
|
default_metadata_tags[i].tag,
|
|
equivalent_metadata_tags[index].tag);
|
|
}
|
|
}
|
|
|
|
if (equivalent_metadata_tags[index].exif_tag_index > -1)
|
|
{
|
|
gint i_exif = equivalent_metadata_tags[index].exif_tag_index;
|
|
const gchar *exif_tag_str = exif_equivalent_tags[i_exif].tag;
|
|
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
exif_tag_str,
|
|
NULL);
|
|
if (text && *text)
|
|
set_tag_string (g_metadata, exif_tag_str, text, FALSE);
|
|
}
|
|
}
|
|
|
|
if (text)
|
|
g_free (text);
|
|
}
|
|
else if (default_metadata_tags[i].mode == MODE_LIST)
|
|
{
|
|
/* MIGHT DO SOMETHING HERE */
|
|
}
|
|
|
|
/* COMBO TAGS */
|
|
|
|
else if (default_metadata_tags[i].mode == MODE_COMBO)
|
|
{
|
|
GtkComboBoxText *combo;
|
|
gint32 value;
|
|
|
|
combo = GTK_COMBO_BOX_TEXT (widget);
|
|
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_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
"Iptc.Application2.Urgency",
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
gchar *save;
|
|
|
|
save = g_strdup_printf ("%d", value);
|
|
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
save, FALSE);
|
|
set_tag_string (g_metadata, "Iptc.Application2.Urgency",
|
|
save, FALSE);
|
|
g_free (save);
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.xmpRights.Marked",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
/* Description tab - Copyright Status */
|
|
if (value == 0)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
gchar *save_value;
|
|
|
|
if (value == 1)
|
|
save_value = g_strdup_printf ("%s", "True");
|
|
else /* (value == 2) */
|
|
save_value = g_strdup_printf ("%s", "False");
|
|
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
save_value, FALSE);
|
|
g_free (save_value);
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.xmp.Rating", default_metadata_tags[i].tag))
|
|
{
|
|
if (value == 0)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
gchar *save;
|
|
|
|
save = g_strdup_printf ("%d", value);
|
|
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
save, FALSE);
|
|
g_free (save);
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.DICOM.PatientSex",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
switch (value)
|
|
{
|
|
case 0:
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
break;
|
|
|
|
case 1:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"male", FALSE);
|
|
break;
|
|
|
|
case 2:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"female", FALSE);
|
|
break;
|
|
|
|
case 3:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"other", FALSE);
|
|
break;
|
|
}
|
|
}
|
|
else if (! strcmp ("Exif.GPSInfo.GPSLongitudeRef",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
switch (value)
|
|
{
|
|
case 0:
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
break;
|
|
|
|
case 1:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"E", FALSE);
|
|
break;
|
|
|
|
case 2:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"W", FALSE);
|
|
break;
|
|
}
|
|
}
|
|
else if (! strcmp ("Exif.GPSInfo.GPSLatitudeRef",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
switch (value)
|
|
{
|
|
case 0:
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
break;
|
|
|
|
case 1:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"N", FALSE);
|
|
break;
|
|
|
|
case 2:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"S", FALSE);
|
|
break;
|
|
}
|
|
}
|
|
else if (! strcmp ("Exif.GPSInfo.GPSAltitudeRef",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
switch (value)
|
|
{
|
|
case 0:
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
break;
|
|
|
|
case 1:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"0", FALSE);
|
|
break;
|
|
|
|
case 2:
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
"1", FALSE);
|
|
break;
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.plus.ModelReleaseStatus",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
if (value == 0)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
modelreleasestatus[value].data, FALSE);
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.plus.PropertyReleaseStatus",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
if (value == 0)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
propertyreleasestatus[value].data, FALSE);
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.plus.MinorModelAgeDisclosure",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
if (value == 0)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
minormodelagedisclosure[value].data, FALSE);
|
|
}
|
|
}
|
|
else if (! strcmp ("Xmp.iptcExt.DigitalSourceType",
|
|
default_metadata_tags[i].tag))
|
|
{
|
|
if (value == 0)
|
|
{
|
|
gexiv2_metadata_try_clear_tag (GEXIV2_METADATA (g_metadata),
|
|
default_metadata_tags[i].tag,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
set_tag_string (g_metadata, default_metadata_tags[i].tag,
|
|
digitalsourcetype[value].data, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
gimp_image_set_metadata (image, 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)
|
|
{
|
|
metadata_editor *meta_info = data;
|
|
GtkWidget *entry;
|
|
gint32 selection;
|
|
gchar alt_str[256];
|
|
double alt_d;
|
|
|
|
selection = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
|
|
|
|
entry = metadata_editor_get_widget (meta_info, "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;
|
|
}
|