Gimp/plug-ins/metadata/metadata-xml.c
Jacob Boerema 8969bbcee8 plug-ins: Remove dependency on GtkBuilder from metadata-editor
Instead of loading the GtkBuilder .ui file we now create all widgets in
code.
Added several support functions to reduce code copy/pasting and making
additional widgets and supporting more metadata easier.
The overall layout should still look the same, with a few exceptions:
- Each notebook page only uses one grid. This makes it possible to align
all data entry widgets.
- Featured Organization and it's code were two treeviews next to each
other. These are now organized below each other to make automatic code
generation easier.
- Since we needed to touch this code anyway, I also fixed Xmp.dc.creator
and Xmp.iptcExt.ModelAge to be multiline. This closes #7286.
- The old icons used for the date button, add, and remove row buttons
were replaced by gimp-grid, list-add and list-remove.

Since this was the last .ui file used in GIMP plug-ins, we remove all
files from the .ui subdirectory and references to that.

Note that there are several more places where GtkBuilder is used, but
those cases uses strings defined in code instead of .ui files.
2023-05-10 13:25:12 -04:00

1137 lines
37 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 <gexiv2/gexiv2.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "libgimp/stdplugins-intl.h"
#include "metadata-misc.h"
#include "metadata-xml.h"
#include "metadata-tags.h"
#include "metadata-editor.h"
extern gboolean gimpmetadata;
extern gboolean force_write;
gboolean xmptag;
gboolean iptctag;
gboolean tagvalue;
gboolean taglistvalue;
gboolean tagname;
gboolean tagmode;
gboolean listelement;
gboolean element;
gchar *str_tag_value;
gchar *str_tag_name;
gchar *str_tag_mode;
gchar *str_element;
gchar *list_tag_data[256][256];
gint row_count = 0;
gint item_count = 0;
static void get_list_elements (GString *xmldata,
int element_count,
gchar **rowtagdata);
void
xml_parser_start_element (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
gpointer user_data,
GError **error)
{
if (strcmp (element_name, "gimp-metadata") == 0)
{
gimpmetadata = TRUE;
}
else if (strcmp (element_name, "iptc-tag") == 0)
{
item_count = 0;
row_count = 0;
iptctag = TRUE;
}
else if (strcmp (element_name, "xmp-tag") == 0)
{
item_count = 0;
row_count = 0;
xmptag = TRUE;
}
else if (strcmp (element_name, "tag-value") == 0)
{
tagvalue = TRUE;
}
else if (strcmp (element_name, "tag-list-value") == 0)
{
taglistvalue = TRUE;
}
else if (strcmp (element_name, "tag-name") == 0)
{
tagname = TRUE;
}
else if (strcmp (element_name, "tag-mode") == 0)
{
tagmode = TRUE;
}
else if (strcmp (element_name, "list-element") == 0)
{
listelement = TRUE;
row_count += 1;
}
else if (strcmp (element_name, "element") == 0)
{
element = TRUE;
item_count += 1;
}
}
void
xml_parser_data (GMarkupParseContext *context,
const gchar *text,
gsize text_len,
gpointer user_data,
GError **error)
{
if (tagvalue)
{
if (str_tag_value)
g_free(str_tag_value);
if (text)
str_tag_value = g_strdup(text);
else
str_tag_value = g_strconcat("", NULL);
}
else if (tagname)
{
if (str_tag_name)
g_free(str_tag_name);
if (text)
str_tag_name = g_strdup(text);
else
str_tag_name = g_strconcat("", NULL);
}
else if (tagmode)
{
if (str_tag_mode)
g_free(str_tag_mode);
if (text)
str_tag_mode = g_strdup(text);
else
str_tag_mode = g_strconcat("", NULL);
}
else if (element)
{
if (str_element)
g_free(str_element);
if (text)
str_element = g_strdup(text);
else
str_element = g_strconcat("", NULL);
}
}
void
set_tag_ui (metadata_editor *args,
gint index,
gchar *name,
gchar *value,
gchar* mode)
{
GtkWidget *widget = NULL;
widget = GTK_WIDGET (metadata_editor_get_widget (args, str_tag_name));
if (!strcmp ("single", mode))
{
GtkEntry *entry_widget;
gchar *value_utf;
value_utf = g_locale_to_utf8 (str_tag_value, -1, NULL, NULL, NULL);
entry_widget = GTK_ENTRY (widget);
gtk_entry_set_text (entry_widget, value_utf);
g_free (value_utf);
}
else if (!strcmp ("multi", mode))
{
GtkTextView *text_view;
GtkTextBuffer *buffer;
gchar *value_utf;
value_utf = g_locale_to_utf8 (str_tag_value, -1, NULL, NULL, NULL);
text_view = GTK_TEXT_VIEW (widget);
buffer = gtk_text_view_get_buffer (text_view);
gtk_text_buffer_set_text (buffer, value_utf, -1);
g_free (value_utf);
}
else if (!strcmp ("combo", mode))
{
gint32 value;
gchar *value_utf;
value_utf = g_locale_to_utf8 (str_tag_value, -1, NULL, NULL, NULL);
value = atoi(value_utf);
gtk_combo_box_set_active (GTK_COMBO_BOX(widget), value);
g_free (value_utf);
}
else if (!strcmp ("list", mode))
{
GtkTreeModel *treemodel;
GtkListStore *liststore;
GtkTreeIter iter;
gint number_of_rows;
gint row;
gint item;
liststore = GTK_LIST_STORE(gtk_tree_view_get_model((GtkTreeView *)widget));
treemodel = GTK_TREE_MODEL (liststore);
number_of_rows =
gtk_tree_model_iter_n_children(GTK_TREE_MODEL(liststore), NULL);
/* Clear all current values */
for (row = number_of_rows; row > -1; row--)
{
if (gtk_tree_model_iter_nth_child(treemodel, &iter, NULL, row))
{
gtk_list_store_remove(liststore, &iter);
}
}
/* Add new values values */
if (!strcmp (LICENSOR_HEADER, name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_LICENSOR_NAME, list_tag_data[row][1],
COL_LICENSOR_ID, list_tag_data[row][2],
COL_LICENSOR_PHONE1, list_tag_data[row][3],
COL_LICENSOR_PHONE_TYPE1, list_tag_data[row][4],
COL_LICENSOR_PHONE2, list_tag_data[row][5],
COL_LICENSOR_PHONE_TYPE2, list_tag_data[row][6],
COL_LICENSOR_EMAIL, list_tag_data[row][7],
COL_LICENSOR_WEB, list_tag_data[row][8],
-1);
for (item = 1; item < n_licensor + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
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, NULL,
COL_LICENSOR_PHONE2, NULL,
COL_LICENSOR_PHONE_TYPE2, NULL,
COL_LICENSOR_EMAIL, NULL,
COL_LICENSOR_WEB, NULL,
-1);
}
}
}
else if (!strcmp (IMAGECREATOR_HEADER, name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_IMG_CR8_NAME, list_tag_data[row][1],
COL_IMG_CR8_ID, list_tag_data[row][2],
-1);
for (item = 1; item < n_imagecreator + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_IMG_CR8_NAME, NULL,
COL_IMG_CR8_ID, NULL,
-1);
}
}
}
else if (!strcmp (ARTWORKOROBJECT_HEADER, name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_AOO_TITLE, list_tag_data[row][1],
COL_AOO_DATE_CREAT, list_tag_data[row][2],
COL_AOO_CREATOR, list_tag_data[row][3],
COL_AOO_SOURCE, list_tag_data[row][4],
COL_AOO_SRC_INV_ID, list_tag_data[row][5],
COL_AOO_CR_NOT, list_tag_data[row][6],
-1);
for (item = 1; item < n_artworkorobject + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
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);
}
}
}
else if (!strcmp (REGISTRYID_HEADER, name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_REGISTRY_ORG_ID, list_tag_data[row][1],
COL_REGISTRY_ITEM_ID, list_tag_data[row][2],
-1);
for (item = 1; item < n_registryid + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_REGISTRY_ORG_ID, NULL,
COL_REGISTRY_ITEM_ID, NULL,
-1);
}
}
}
else if (!strcmp (COPYRIGHTOWNER_HEADER, name))
{
if (row_count > 0)
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_CR_OWNER_NAME, list_tag_data[row][1],
COL_CR_OWNER_ID, list_tag_data[row][2],
-1);
for (item = 1; item < n_copyrightowner + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_CR_OWNER_NAME, NULL,
COL_CR_OWNER_ID, NULL,
-1);
}
}
}
else if (!strcmp (LOCATIONSHOWN_HEADER, name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_LOC_SHO_SUB_LOC, list_tag_data[row][1],
COL_LOC_SHO_CITY, list_tag_data[row][2],
COL_LOC_SHO_STATE_PROV, list_tag_data[row][3],
COL_LOC_SHO_CNTRY, list_tag_data[row][4],
COL_LOC_SHO_CNTRY_ISO, list_tag_data[row][5],
COL_LOC_SHO_CNTRY_WRLD_REG, list_tag_data[row][6],
-1);
for (item = 1; item < n_locationshown + 1; item++)
{
if (list_tag_data[row][item])
{
if (list_tag_data[row][item])
g_free(list_tag_data[row][item]);
}
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
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 if (!strcmp ("Xmp.iptcExt.OrganisationInImageName", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_NAME, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_NAME, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageCode", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_CODE, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_ORG_IMG_CODE, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.plus.PropertyReleaseID", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_PROP_REL_ID, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_PROP_REL_ID, NULL,
-1);
}
}
}
else if (!strcmp ("Xmp.plus.ModelReleaseID", name))
{
for (row = 1; row < row_count+1; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_MOD_REL_ID, list_tag_data[row][1],
-1);
if (list_tag_data[row][1])
{
if (list_tag_data[row][1])
g_free(list_tag_data[row][1]);
}
}
if (row_count < 2)
{
for (row = 0; row < 2 - row_count; row++)
{
gtk_list_store_append (liststore, &iter);
gtk_list_store_set (liststore, &iter,
COL_MOD_REL_ID, NULL,
-1);
}
}
}
}
}
const gchar *
get_tag_ui_text (metadata_editor *args,
gchar *name,
gchar *mode)
{
GtkWidget *widget = NULL;
widget = metadata_editor_get_widget (args, name);
if (! strcmp ("single", mode))
{
GtkEntry *entry = GTK_ENTRY (widget);
return gtk_entry_get_text (entry);
}
else if (!strcmp ("multi", mode))
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
GtkTextBuffer *buffer;
GtkTextIter start;
GtkTextIter end;
buffer = gtk_text_view_get_buffer (text_view);
gtk_text_buffer_get_start_iter (buffer, &start);
gtk_text_buffer_get_end_iter (buffer, &end);
return gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
}
return NULL;
}
static void
get_list_elements (GString *xmldata, int element_count, gchar **rowtagdata)
{
gint list_idx;
g_string_append (xmldata, "\t\t\t<list-element>\n");
for (list_idx = 0; list_idx < element_count; list_idx++)
{
g_string_append (xmldata, "\t\t\t\t<element>");
if (rowtagdata && rowtagdata[list_idx] && strlen(rowtagdata[list_idx]) > 0)
{
g_string_append (xmldata, rowtagdata[list_idx]);
}
g_string_append (xmldata, "</element>\n");
}
g_string_append (xmldata, "\t\t\t</list-element>\n");
}
gchar *
get_tag_ui_list (metadata_editor *args, gchar *name, gchar *mode)
{
GtkWidget *widget = NULL;
GtkTreeModel *treemodel;
GtkListStore *liststore;
GtkTreeIter iter;
GString *xmldata;
gint number_of_rows;
gint row;
gint has_data;
gchar *tagdata[256][256];
has_data = FALSE;
xmldata = g_string_new ("");
widget = metadata_editor_get_widget (args, name);
liststore = GTK_LIST_STORE(gtk_tree_view_get_model((GtkTreeView *)widget));
treemodel = GTK_TREE_MODEL (liststore);
number_of_rows =
gtk_tree_model_iter_n_children(GTK_TREE_MODEL(liststore), NULL);
for (row = 0; row < number_of_rows; row++)
{
if (gtk_tree_model_iter_nth_child(treemodel, &iter, NULL, row))
{
if (!strcmp (LICENSOR_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_LICENSOR_NAME, &tagdata[row][0],
COL_LICENSOR_ID, &tagdata[row][1],
COL_LICENSOR_PHONE1, &tagdata[row][2],
COL_LICENSOR_PHONE_TYPE1, &tagdata[row][3],
COL_LICENSOR_PHONE2, &tagdata[row][4],
COL_LICENSOR_PHONE_TYPE2, &tagdata[row][5],
COL_LICENSOR_EMAIL, &tagdata[row][6],
COL_LICENSOR_WEB, &tagdata[row][7],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0) ||
(tagdata[row][2] != NULL && strlen(tagdata[row][2]) > 0) ||
(tagdata[row][3] != NULL && strlen(tagdata[row][3]) > 0) ||
(tagdata[row][4] != NULL && strlen(tagdata[row][4]) > 0) ||
(tagdata[row][5] != NULL && strlen(tagdata[row][5]) > 0) ||
(tagdata[row][6] != NULL && strlen(tagdata[row][6]) > 0) ||
(tagdata[row][7] != NULL && strlen(tagdata[row][7]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 8, tagdata[row]);
}
}
else if (!strcmp (COPYRIGHTOWNER_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_CR_OWNER_NAME, &tagdata[row][0],
COL_CR_OWNER_ID, &tagdata[row][1],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0))
{
has_data = TRUE;
g_string_append (xmldata, "\t\t\t<list-element>\n");
g_string_append (xmldata, "\t\t\t\t<element>");
g_string_append (xmldata, tagdata[row][0]);
g_string_append (xmldata, "</element>\n");
g_string_append (xmldata, "\t\t\t\t<element>");
g_string_append (xmldata, tagdata[row][1]);
g_string_append (xmldata, "</element>\n");
g_string_append (xmldata, "\t\t\t</list-element>\n");
}
}
else if (!strcmp (IMAGECREATOR_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_IMG_CR8_NAME, &tagdata[row][0],
COL_IMG_CR8_ID, &tagdata[row][1],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 2, tagdata[row]);
}
}
else if (!strcmp (ARTWORKOROBJECT_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_AOO_TITLE, &tagdata[row][0],
COL_AOO_DATE_CREAT, &tagdata[row][1],
COL_AOO_CREATOR, &tagdata[row][2],
COL_AOO_SOURCE, &tagdata[row][3],
COL_AOO_SRC_INV_ID, &tagdata[row][4],
COL_AOO_CR_NOT, &tagdata[row][5],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0) ||
(tagdata[row][2] != NULL && strlen(tagdata[row][2]) > 0) ||
(tagdata[row][3] != NULL && strlen(tagdata[row][3]) > 0) ||
(tagdata[row][4] != NULL && strlen(tagdata[row][4]) > 0) ||
(tagdata[row][5] != NULL && strlen(tagdata[row][5]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 6, tagdata[row]);
}
}
else if (!strcmp (REGISTRYID_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_REGISTRY_ORG_ID, &tagdata[row][0],
COL_REGISTRY_ITEM_ID, &tagdata[row][1],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 2, tagdata[row]);
}
}
else if (!strcmp (LOCATIONSHOWN_HEADER, name))
{
gtk_tree_model_get (treemodel, &iter,
COL_LOC_SHO_SUB_LOC, &tagdata[row][0],
COL_LOC_SHO_CITY, &tagdata[row][1],
COL_LOC_SHO_STATE_PROV, &tagdata[row][2],
COL_LOC_SHO_CNTRY, &tagdata[row][3],
COL_LOC_SHO_CNTRY_ISO, &tagdata[row][4],
COL_LOC_SHO_CNTRY_WRLD_REG, &tagdata[row][5],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0) ||
(tagdata[row][1] != NULL && strlen(tagdata[row][1]) > 0) ||
(tagdata[row][2] != NULL && strlen(tagdata[row][2]) > 0) ||
(tagdata[row][3] != NULL && strlen(tagdata[row][3]) > 0) ||
(tagdata[row][4] != NULL && strlen(tagdata[row][4]) > 0) ||
(tagdata[row][5] != NULL && strlen(tagdata[row][5]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 6, tagdata[row]);
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageName", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_ORG_IMG_NAME, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
else if (!strcmp ("Xmp.iptcExt.OrganisationInImageCode", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_ORG_IMG_CODE, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
else if (!strcmp ("Xmp.plus.PropertyReleaseID", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_PROP_REL_ID, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
else if (!strcmp ("Xmp.plus.ModelReleaseID", name))
{
gtk_tree_model_get (treemodel, &iter,
COL_MOD_REL_ID, &tagdata[row][0],
-1);
if ((tagdata[row][0] != NULL && strlen(tagdata[row][0]) > 0))
{
has_data = TRUE;
get_list_elements (xmldata, 1, tagdata[row]);
}
}
}
}
if (has_data == TRUE)
{
gchar *xml;
xml = g_strdup (xmldata->str);
g_string_free(xmldata, TRUE);
return xml;
}
g_string_free(xmldata, TRUE);
return NULL;
}
gint
get_tag_ui_combo (metadata_editor *args, gchar *name, gchar *mode)
{
return gtk_combo_box_get_active (GTK_COMBO_BOX(metadata_editor_get_widget (args, name)));
}
void
xml_parser_end_element (GMarkupParseContext *context,
const gchar *element_name,
gpointer user_data,
GError **error)
{
metadata_editor *args;
int i;
args = user_data;
if (strcmp (element_name, "gimp-metadata") == 0)
{
gimpmetadata = FALSE;
}
else if (strcmp (element_name, "iptc-tag") == 0)
{
iptctag = FALSE;
#ifdef _ENABLE_IPTC_TAG_
if (str_tag_name && str_tag_value)
{
/* make sure to only allow supported tags */
for (i = 0; i < n_equivalent_metadata_tags; i++)
{
if (strcmp(equivalent_metadata_tags[i].tag, str_tag_name) == 0)
{
#ifdef _SET_IPTC_TAG_
set_tag_ui (args, i, str_tag_name, str_tag_value,
equivalent_metadata_tags[i].mode);
#endif
if (force_write == TRUE)
gexiv2_metadata_set_tag_string (args->metadata,
str_tag_name,
str_tag_value);
break;
}
}
}
#endif
}
else if (strcmp (element_name, "xmp-tag") == 0)
{
xmptag = FALSE;
if (strcmp (str_tag_mode, "list") != 0)
{
if (str_tag_name && str_tag_value)
{
/* make sure to only allow supported tags */
for (i = 0; i < n_default_metadata_tags; i++)
{
if (strcmp(default_metadata_tags[i].tag, str_tag_name) == 0)
{
set_tag_ui (args, i, str_tag_name, str_tag_value,
default_metadata_tags[i].mode);
#ifdef _ENABLE_FORCE_WRITE_
if (force_write == TRUE)
gexiv2_metadata_set_tag_string (args->metadata,
str_tag_name,
str_tag_value);
#endif
break;
}
}
}
}
else if (strcmp (str_tag_mode, "list") == 0)
{
if (row_count > 0)
{
/* make sure to only allow supported tags */
for (i = 0; i < n_default_metadata_tags; i++)
{
if (strcmp(default_metadata_tags[i].tag, str_tag_name) == 0)
{
set_tag_ui (args, i, str_tag_name, str_tag_value,
default_metadata_tags[i].mode);
#ifdef _ENABLE_FORCE_WRITE_
if (force_write == TRUE)
gexiv2_metadata_set_tag_string (args->metadata,
str_tag_name,
str_tag_value);
#endif
break;
}
}
}
row_count = 0;
item_count = 0;
}
}
else if (strcmp (element_name, "tag-value") == 0)
{
tagvalue = FALSE;
}
else if (strcmp (element_name, "tag-list-value") == 0)
{
taglistvalue = FALSE;
}
else if (strcmp (element_name, "tag-name") == 0)
{
tagname = FALSE;
}
else if (strcmp (element_name, "tag-mode") == 0)
{
tagmode = FALSE;
}
else if (strcmp (element_name, "list-element") == 0)
{
listelement = FALSE;
item_count = 0;
}
else if (strcmp (element_name, "element") == 0)
{
element = FALSE;
list_tag_data[row_count][item_count] = g_strdup(str_element);
}
}
gboolean
xml_parser_parse_file (GimpXmlParser *parser,
const gchar *filename,
GError **error)
{
GIOChannel *io;
gboolean success;
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
io = g_io_channel_new_file (filename, "r", error);
if (!io)
return FALSE;
success = xml_parser_parse_io_channel (parser, io, error);
g_io_channel_unref (io);
return success;
}
GimpXmlParser *
xml_parser_new (const GMarkupParser *markup_parser,
gpointer user_data)
{
GimpXmlParser *parser;
g_return_val_if_fail (markup_parser != NULL, NULL);
parser = g_slice_new (GimpXmlParser);
parser->context = g_markup_parse_context_new (markup_parser,
0, user_data, NULL);
return parser;
}
void
xml_parser_free (GimpXmlParser *parser)
{
g_return_if_fail (parser != NULL);
g_markup_parse_context_free (parser->context);
g_slice_free (GimpXmlParser, parser);
}
gboolean
parse_encoding (const gchar *text,
gint text_len,
gchar **encoding)
{
const gchar *start;
const gchar *end;
gint i;
g_return_val_if_fail (text, FALSE);
if (text_len < 20)
return FALSE;
start = g_strstr_len (text, text_len, "<?xml");
if (!start)
return FALSE;
end = g_strstr_len (start, text_len - (start - text), "?>");
if (!end)
return FALSE;
*encoding = NULL;
text_len = end - start;
if (text_len < 12)
return TRUE;
start = g_strstr_len (start + 1, text_len - 1, "encoding");
if (!start)
return TRUE;
start += 8;
while (start < end && *start == ' ')
start++;
if (*start != '=')
return TRUE;
start++;
while (start < end && *start == ' ')
start++;
if (*start != '\"' && *start != '\'')
return TRUE;
text_len = end - start;
if (text_len < 1)
return TRUE;
for (i = 1; i < text_len; i++)
if (start[i] == start[0])
break;
if (i == text_len || i < 3)
return TRUE;
*encoding = g_strndup (start + 1, i - 1);
return TRUE;
}
gboolean
xml_parser_parse_io_channel (GimpXmlParser *parser,
GIOChannel *io,
GError **error)
{
GIOStatus status;
gchar buffer[4096];
gsize len = 0;
gsize bytes;
const gchar *io_encoding;
gchar *encoding = NULL;
g_return_val_if_fail (parser != NULL, FALSE);
g_return_val_if_fail (io != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
io_encoding = g_io_channel_get_encoding (io);
if (g_strcmp0 (io_encoding, "UTF-8"))
{
g_warning ("xml_parser_parse_io_channel():\n"
"The encoding has already been set on this GIOChannel!");
return FALSE;
}
/* try to determine the encoding */
g_io_channel_set_encoding (io, NULL, NULL);
while (len < sizeof (buffer))
{
status = g_io_channel_read_chars (io, buffer + len, 1, &bytes, error);
len += bytes;
if (status == G_IO_STATUS_ERROR)
return FALSE;
if (status == G_IO_STATUS_EOF)
break;
if (parse_encoding (buffer, len, &encoding))
break;
}
if (encoding)
{
if (! g_io_channel_set_encoding (io, encoding, error))
return FALSE;
if (encoding)
g_free (encoding);
}
else
{
g_io_channel_set_encoding (io, "UTF-8", NULL);
}
while (TRUE)
{
if (!g_markup_parse_context_parse (parser->context, buffer, len, error))
return FALSE;
status = g_io_channel_read_chars (io,
buffer, sizeof (buffer), &len, error);
switch (status)
{
case G_IO_STATUS_ERROR:
return FALSE;
case G_IO_STATUS_EOF:
return g_markup_parse_context_end_parse (parser->context, error);
case G_IO_STATUS_NORMAL:
case G_IO_STATUS_AGAIN:
break;
}
}
}