plug-ins: create metadata-viewer gui from code

The metadata-viewer uses a GtkBuilder .ui file to create the interface.
In GIMP we prefer our interfaces to be created in code and these builder
files are also not available anymore in GTK4.

This commit removes the .ui file and support code, and creates the
interface from code in our plug-in.
This commit is contained in:
Jacob Boerema 2023-04-30 15:13:38 -04:00
parent bca4535c40
commit 9c11b40393
4 changed files with 154 additions and 273 deletions

View File

@ -21,8 +21,6 @@
#include "config.h" #include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include <gexiv2/gexiv2.h> #include <gexiv2/gexiv2.h>
#include <libgimp/gimp.h> #include <libgimp/gimp.h>
@ -102,7 +100,9 @@ static gboolean metadata_viewer_dialog (GimpImage *image,
GimpMetadata *g_metadata, GimpMetadata *g_metadata,
GError **error); GError **error);
static void metadata_dialog_set_metadata (GExiv2Metadata *metadata, static void metadata_dialog_set_metadata (GExiv2Metadata *metadata,
GtkBuilder *builder); GtkListStore *exif_store,
GtkListStore *xmp_store,
GtkListStore *iptc_store);
static void metadata_dialog_add_multiple_values (GExiv2Metadata *metadata, static void metadata_dialog_add_multiple_values (GExiv2Metadata *metadata,
const gchar *tag, const gchar *tag,
GtkListStore *store, GtkListStore *store,
@ -245,37 +245,22 @@ metadata_viewer_dialog (GimpImage *image,
GimpMetadata *g_metadata, GimpMetadata *g_metadata,
GError **error) GError **error)
{ {
GtkBuilder *builder; gchar *title;
GtkWidget *dialog; gchar *name;
GtkWidget *metadata_vbox; GtkWidget *dialog;
GtkWidget *content_area; GtkWidget *content_area;
gchar *ui_file; GtkWidget *metadata_vbox;
gchar *title; GtkWidget *notebook;
gchar *name; GtkWidget *scrolled_win;
GError *local_error = NULL; GtkWidget *list_view;
GExiv2Metadata *metadata; GtkWidget *label;
GtkListStore *exif_store, *xmp_store, *iptc_store;
GtkCellRenderer *rend;
GtkTreeViewColumn *col;
GExiv2Metadata *metadata;
metadata = GEXIV2_METADATA(g_metadata); metadata = GEXIV2_METADATA(g_metadata);
builder = gtk_builder_new ();
ui_file = g_build_filename (gimp_data_directory (),
"ui", "plug-ins", "plug-in-metadata-viewer.ui", NULL);
if (! gtk_builder_add_from_file (builder, ui_file, &local_error))
{
if (! local_error)
local_error = g_error_new_literal (G_FILE_ERROR, 0,
_("Error loading metadata-viewer dialog."));
g_propagate_error (error, local_error);
g_free (ui_file);
g_object_unref (builder);
return FALSE;
}
g_free (ui_file);
name = gimp_image_get_name (image); name = gimp_image_get_name (image);
title = g_strdup_printf (_("Metadata Viewer: %s"), name); title = g_strdup_printf (_("Metadata Viewer: %s"), name);
g_free (name); g_free (name);
@ -297,12 +282,138 @@ metadata_viewer_dialog (GimpImage *image,
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
metadata_vbox = GTK_WIDGET (gtk_builder_get_object (builder, /* Top-level Box */
"metadata-vbox"));
gtk_container_set_border_width (GTK_CONTAINER (metadata_vbox), 12);
gtk_box_pack_start (GTK_BOX (content_area), metadata_vbox, TRUE, TRUE, 0);
metadata_dialog_set_metadata (metadata, builder); metadata_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (content_area), metadata_vbox);
gtk_container_set_border_width (GTK_CONTAINER (metadata_vbox), 12);
gtk_widget_show (metadata_vbox);
notebook = gtk_notebook_new ();
gtk_box_pack_start (GTK_BOX (metadata_vbox), notebook, TRUE, TRUE, 0);
/* EXIF tab */
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 6);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
exif_store = gtk_list_store_new (NUM_EXIF_COLS,
G_TYPE_STRING, /* column-name c_exif_tag */
G_TYPE_STRING); /* column-name c_exif_value */
list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (exif_store));
gtk_widget_set_vexpand (list_view, TRUE);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Exif Tag"),
rend,
"text", C_EXIF_TAG,
NULL);
gtk_tree_view_column_set_resizable (col, TRUE);
gtk_tree_view_column_set_spacing (col, 3);
gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), col);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Value"),
rend,
"text", C_EXIF_VALUE,
NULL);
gtk_tree_view_column_set_resizable (col, TRUE);
gtk_tree_view_column_set_spacing (col, 3);
gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), col);
label = gtk_label_new (_("Exif"));
gtk_widget_show (label);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_win, label);
gtk_container_add (GTK_CONTAINER (scrolled_win), list_view);
gtk_widget_show (list_view);
gtk_widget_show (scrolled_win);
/* XMP tab */
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 6);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
xmp_store = gtk_list_store_new (NUM_XMP_COLS,
G_TYPE_STRING, /* column-name c_xmp_tag */
G_TYPE_STRING); /* column-name c_xmp_value */
list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (xmp_store));
gtk_widget_set_vexpand (list_view, TRUE);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("XMP Tag"),
rend,
"text", C_XMP_TAG,
NULL);
gtk_tree_view_column_set_resizable (col, TRUE);
gtk_tree_view_column_set_spacing (col, 3);
gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), col);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Value"),
rend,
"text", C_XMP_VALUE,
NULL);
gtk_tree_view_column_set_resizable (col, TRUE);
gtk_tree_view_column_set_spacing (col, 3);
gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), col);
label = gtk_label_new (_("XMP"));
gtk_widget_show (label);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_win, label);
gtk_container_add (GTK_CONTAINER (scrolled_win), list_view);
gtk_widget_show (list_view);
gtk_widget_show (scrolled_win);
/* IPTC tab */
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 6);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win), GTK_SHADOW_IN);
iptc_store = gtk_list_store_new (NUM_IPTC_COLS,
G_TYPE_STRING, /* column-name c_iptc_tag */
G_TYPE_STRING); /* column-name c_iptc_value */
list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (iptc_store));
gtk_widget_set_vexpand (list_view, TRUE);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("IPTC Tag"),
rend,
"text", C_IPTC_TAG,
NULL);
gtk_tree_view_column_set_resizable (col, TRUE);
gtk_tree_view_column_set_spacing (col, 3);
gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), col);
rend = gtk_cell_renderer_text_new ();
col = gtk_tree_view_column_new_with_attributes (_("Value"),
rend,
"text", C_IPTC_VALUE,
NULL);
gtk_tree_view_column_set_resizable (col, TRUE);
gtk_tree_view_column_set_spacing (col, 3);
gtk_tree_view_append_column (GTK_TREE_VIEW (list_view), col);
label = gtk_label_new (_("IPTC"));
gtk_widget_show (label);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled_win, label);
gtk_container_add (GTK_CONTAINER (scrolled_win), list_view);
gtk_widget_show (list_view);
gtk_widget_show (scrolled_win);
gtk_widget_show (notebook);
/* Add the metadata to the tree views */
metadata_dialog_set_metadata (metadata, exif_store, xmp_store, iptc_store);
g_object_unref (exif_store);
g_object_unref (xmp_store);
g_object_unref (iptc_store);
gtk_dialog_run (GTK_DIALOG (dialog)); gtk_dialog_run (GTK_DIALOG (dialog));
@ -314,32 +425,30 @@ metadata_viewer_dialog (GimpImage *image,
static void static void
metadata_dialog_set_metadata (GExiv2Metadata *metadata, metadata_dialog_set_metadata (GExiv2Metadata *metadata,
GtkBuilder *builder) GtkListStore *exif_store,
GtkListStore *xmp_store,
GtkListStore *iptc_store)
{ {
gchar **tags; gchar **tags;
GtkListStore *store;
/* load exif tags */ /* load exif tags */
tags = gexiv2_metadata_get_exif_tags (metadata); tags = gexiv2_metadata_get_exif_tags (metadata);
store = GTK_LIST_STORE (gtk_builder_get_object (builder, "exif-liststore"));
metadata_dialog_append_tags (metadata, tags, store, C_EXIF_TAG, C_EXIF_VALUE, FALSE); metadata_dialog_append_tags (metadata, tags, exif_store, C_EXIF_TAG, C_EXIF_VALUE, FALSE);
g_strfreev (tags); g_strfreev (tags);
/* load xmp tags */ /* load xmp tags */
tags = gexiv2_metadata_get_xmp_tags (metadata); tags = gexiv2_metadata_get_xmp_tags (metadata);
store = GTK_LIST_STORE (gtk_builder_get_object (builder, "xmp-liststore"));
metadata_dialog_append_tags (metadata, tags, store, C_XMP_TAG, C_XMP_VALUE, FALSE); metadata_dialog_append_tags (metadata, tags, xmp_store, C_XMP_TAG, C_XMP_VALUE, FALSE);
g_strfreev (tags); g_strfreev (tags);
/* load iptc tags */ /* load iptc tags */
tags = gexiv2_metadata_get_iptc_tags (metadata); tags = gexiv2_metadata_get_iptc_tags (metadata);
store = GTK_LIST_STORE (gtk_builder_get_object (builder, "iptc-liststore"));
metadata_dialog_append_tags (metadata, tags, store, C_IPTC_TAG, C_IPTC_VALUE, TRUE); metadata_dialog_append_tags (metadata, tags, iptc_store, C_IPTC_TAG, C_IPTC_VALUE, TRUE);
g_strfreev (tags); g_strfreev (tags);
} }

View File

@ -2,7 +2,6 @@ uidatadir = $(gimpdatadir)/ui/plug-ins
uidata_DATA = \ uidata_DATA = \
plug-in-metadata-editor.ui \ plug-in-metadata-editor.ui \
plug-in-metadata-editor-calendar.ui \ plug-in-metadata-editor-calendar.ui
plug-in-metadata-viewer.ui
EXTRA_DIST = $(uidata_DATA) EXTRA_DIST = $(uidata_DATA)

View File

@ -1,7 +1,6 @@
plugin_ui = [ plugin_ui = [
'plug-in-metadata-editor-calendar.ui', 'plug-in-metadata-editor-calendar.ui',
'plug-in-metadata-editor.ui', 'plug-in-metadata-editor.ui',
'plug-in-metadata-viewer.ui',
] ]
install_data(plugin_ui, install_data(plugin_ui,

View File

@ -1,226 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkListStore" id="exif-liststore">
<columns>
<!-- column-name c_exif_tag -->
<column type="gchararray"/>
<!-- column-name c_exif_value -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkListStore" id="xmp-liststore">
<columns>
<!-- column-name c_xmp_tag -->
<column type="gchararray"/>
<!-- column-name c_xmp_value -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkListStore" id="iptc-liststore">
<columns>
<!-- column-name c_iptc_tag -->
<column type="gchararray"/>
<!-- column-name c_iptc_value -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkVBox" id="metadata-vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkNotebook" id="metadata-notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="scrollable">True</property>
<child>
<object class="GtkScrolledWindow" id="exif-scroll">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="exif-treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">exif-liststore</property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="exif-treeview-selection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="exif_tag_column">
<property name="resizable">True</property>
<property name="spacing">3</property>
<property name="title" translatable="yes">Exif Tag</property>
<child>
<object class="GtkCellRendererText" id="exif_tag_cell_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="exif_value_column">
<property name="resizable">True</property>
<property name="spacing">3</property>
<property name="title" translatable="yes" context="A tag value">Value</property>
<child>
<object class="GtkCellRendererText" id="exif_value_cell_renderer"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="exif">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">4</property>
<property name="ypad">4</property>
<property name="label" translatable="yes">Exif</property>
</object>
<packing>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="xmp-scroll">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="xmp-treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">xmp-liststore</property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="xmp-treeview-selection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="xmp_tag_column">
<property name="resizable">True</property>
<property name="spacing">3</property>
<property name="title" translatable="yes">XMP Tag</property>
<child>
<object class="GtkCellRendererText" id="xmp_tag_cell_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="xmp_value_column">
<property name="resizable">True</property>
<property name="spacing">3</property>
<property name="title" translatable="yes" context="A tag value">Value</property>
<child>
<object class="GtkCellRendererText" id="xmp_value_cell_renderer"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="xmp">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">4</property>
<property name="ypad">4</property>
<property name="label" translatable="yes">XMP</property>
</object>
<packing>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="iptc-scroll">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="iptc-treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">iptc-liststore</property>
<property name="headers_clickable">False</property>
<property name="search_column">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="iptc-treeview-selection"/>
</child>
<child>
<object class="GtkTreeViewColumn" id="iptc_tag_column">
<property name="resizable">True</property>
<property name="spacing">3</property>
<property name="title" translatable="yes">IPTC Tag</property>
<child>
<object class="GtkCellRendererText" id="iptc_tag_cell_renderer"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="iptc_value_column">
<property name="resizable">True</property>
<property name="spacing">3</property>
<property name="title" translatable="yes" context="A tag value">Value</property>
<child>
<object class="GtkCellRendererText" id="iptc_value_cell_renderer"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="iptc">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">4</property>
<property name="ypad">4</property>
<property name="label" translatable="yes">IPTC</property>
</object>
<packing>
<property name="position">2</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</interface>