XMP Model now emits a property-changed signal incl. a detail.

The client can now subscribe to a specific property-change signal. The
detail is provided as <xmp-schema-prefix>:<xmp-property-name>. The
xmpdump test program was used to verify that the implementation works.
This commit is contained in:
Roman Joost 2009-08-15 19:44:32 +10:00
parent f436ffd722
commit dc249d4dc3
4 changed files with 127 additions and 21 deletions

View File

@ -45,6 +45,12 @@ xmpdump_SOURCES = \
xmpdump.c \
base64.h \
base64.c \
xmp-schemas.h \
xmp-schemas.c \
xmp-encode.h \
xmp-encode.c \
xmp-model.h \
xmp-model.c \
xmp-parse.h \
xmp-parse.c

View File

@ -32,24 +32,47 @@
#include "xmp-model.h"
G_DEFINE_TYPE (XMPModel, xmp_model, GTK_TYPE_TREE_STORE)
enum {
PROPERTY_CHANGED,
SCHEMA_CHANGED,
LAST_SIGNAL
};
static void
xmp_model_iface_init (GtkTreeModelIface *iface)
{
}
G_DEFINE_TYPE_WITH_CODE (XMPModel, xmp_model,
GTK_TYPE_TREE_STORE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
xmp_model_iface_init));
static guint xmp_model_signals[LAST_SIGNAL] = { 0 };
static void
xmp_model_init (XMPModel *xmp_model)
{
/* columns defined by the XMPModelColumns enum */
gtk_tree_store_new (XMP_MODEL_NUM_COLUMNS,
G_TYPE_STRING, /* COL_XMP_NAME */
G_TYPE_STRING, /* COL_XMP_VALUE */
G_TYPE_POINTER, /* COL_XMP_VALUE_RAW */
G_TYPE_POINTER, /* COL_XMP_TYPE_XREF */
G_TYPE_POINTER, /* COL_XMP_WIDGET_XREF */
G_TYPE_INT, /* COL_XMP_EDITABLE */
GDK_TYPE_PIXBUF, /* COL_XMP_EDIT_ICON */
G_TYPE_BOOLEAN, /* COL_XMP_VISIBLE */
G_TYPE_INT, /* COL_XMP_WEIGHT */
G_TYPE_BOOLEAN /* COL_XMP_WEIGHT_SET */
);
GType types[XMP_MODEL_NUM_COLUMNS];
types[COL_XMP_NAME] = G_TYPE_STRING;
types[COL_XMP_VALUE] = G_TYPE_STRING;
types[COL_XMP_VALUE_RAW] = G_TYPE_POINTER;
types[COL_XMP_TYPE_XREF] = G_TYPE_POINTER;
types[COL_XMP_WIDGET_XREF] = G_TYPE_POINTER;
types[COL_XMP_EDITABLE] = G_TYPE_INT;
types[COL_XMP_EDIT_ICON] = GDK_TYPE_PIXBUF;
types[COL_XMP_VISIBLE] = G_TYPE_BOOLEAN;
types[COL_XMP_WEIGHT] = G_TYPE_INT;
types[COL_XMP_WEIGHT_SET] = G_TYPE_BOOLEAN;
gtk_tree_store_set_column_types (GTK_TREE_STORE (xmp_model),
XMP_MODEL_NUM_COLUMNS, types);
xmp_model->custom_schemas = NULL;
xmp_model->custom_properties = NULL;
xmp_model->cached_schema = NULL;
@ -58,8 +81,20 @@ xmp_model_init (XMPModel *xmp_model)
static void
xmp_model_class_init (XMPModelClass *klass)
{
xmp_model_signals[PROPERTY_CHANGED] =
g_signal_new ("property-changed",
GIMP_TYPE_XMP_MODEL,
G_SIGNAL_DETAILED,
G_STRUCT_OFFSET (XMPModelClass, property_changed),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1,
GTK_TYPE_TREE_ITER);
klass->property_changed = NULL;
}
/**
* xmp_model_new:
*
@ -473,6 +508,7 @@ parse_set_property (XMPParseContext *context,
COL_XMP_WEIGHT, PANGO_WEIGHT_NORMAL,
COL_XMP_WEIGHT_SET, FALSE,
-1);
xmp_model_property_changed (xmp_model, schema, &child_iter);
break;
case XMP_PTYPE_RESOURCE:
@ -857,7 +893,6 @@ xmp_model_set_scalar_property (XMPModel *xmp_model,
XMPProperty *property = NULL;
GtkTreeIter iter;
GtkTreeIter child_iter;
GtkTreePath *path;
int i;
gchar **value;
@ -909,7 +944,37 @@ xmp_model_set_scalar_property (XMPModel *xmp_model,
COL_XMP_WEIGHT, PANGO_WEIGHT_NORMAL,
COL_XMP_WEIGHT_SET, FALSE,
-1);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (xmp_model), &child_iter);
gtk_tree_model_row_changed (GTK_TREE_MODEL (xmp_model), path, &child_iter);
xmp_model_property_changed (xmp_model, schema, &child_iter);
return TRUE;
}
/**
* xmp_model_property_changed:
* @xmp_model: An #XMPModel
* @schema: An #XMPSchema the property belongs to
* @iter: A valid #GtkTreeIter pointing to the changed row
*
* Emits the "property-changed" event based on the @tree_model with
* detail. The detail is a joined string of xmp-schema-prefix and
* xmp-property-name (e.g. property-changed::dc:DocumentID).
**/
void
xmp_model_property_changed (XMPModel *xmp_model,
XMPSchema *schema,
GtkTreeIter *iter)
{
GQuark detail;
gchar *joined;
const gchar *property_name;
g_return_if_fail (GIMP_IS_XMP_MODEL (xmp_model));
g_return_if_fail (iter != NULL);
gtk_tree_model_get (GTK_TREE_MODEL (xmp_model), iter,
COL_XMP_NAME, &property_name,
-1);
joined = g_strjoin (":", schema->prefix, property_name, NULL);
detail = g_quark_from_string (joined);
g_signal_emit (xmp_model, xmp_model_signals[PROPERTY_CHANGED], detail, iter);
}

View File

@ -62,6 +62,10 @@ struct _XMPModel
struct _XMPModelClass
{
GtkTreeStoreClass parent_class;
void (* property_changed) (XMPModel *xmp_model,
XMPSchema *schema,
GtkTreeIter *iter);
};
/* columns used in the GtkTreeStore model holding the XMP metadata */
@ -112,6 +116,11 @@ gboolean xmp_model_set_scalar_property (XMPModel *xmp_model,
const gchar *property_name,
const gchar *property_value);
/* Signals */
void xmp_model_property_changed (XMPModel *xmp_model,
XMPSchema *schema,
GtkTreeIter *iter);
G_END_DECLS
#endif /* XMP_MODEL_H */

View File

@ -3,8 +3,10 @@
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include "xmp-parse.h"
#include "xmp-encode.h"
static gpointer
@ -105,13 +107,22 @@ static XMPParser xmp_parser = {
print_error
};
static void
property_changed (XMPModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
g_print ("Wuff Wuff!\n");
}
static int
scan_file (const gchar *filename)
{
gchar *contents;
gsize length;
GError *error;
XMPParseContext *context;
gchar *contents;
gsize length;
GError *error;
XMPParseContext *context;
// XMPModel *xmp_model = xmp_model_new ();
g_print ("\nFile: %s\n", filename);
error = NULL;
@ -130,6 +141,19 @@ scan_file (const gchar *filename)
(gpointer) filename,
NULL);
/*
* used for testing the XMPModel
*
g_signal_connect (xmp_model, "property-changed::xmpMM:DocumentID",
G_CALLBACK (property_changed), NULL);
if (! xmp_model_parse_file (xmp_model, filename, &error))
{
xmp_model_free (xmp_model);
return 1;
}
*/
if (! xmp_parse_context_parse (context, contents, length, NULL))
{
xmp_parse_context_free (context);
@ -151,10 +175,12 @@ main (int argc,
char *argv[])
{
g_set_prgname ("xmpdump");
g_type_init();
if (argc > 1)
{
for (argv++, argc--; argc; argv++, argc--)
if (scan_file (*argv) != 0)
return 1;
return 0;
}