builder: Add support for parsing expressions
This commit is contained in:
@@ -520,7 +520,18 @@ gtk_builder_get_parameters (GtkBuilder *builder,
|
||||
const char *property_name = g_intern_string (prop->pspec->name);
|
||||
GValue property_value = G_VALUE_INIT;
|
||||
|
||||
if (G_IS_PARAM_SPEC_OBJECT (prop->pspec) &&
|
||||
if (prop->value)
|
||||
{
|
||||
g_value_init (&property_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
|
||||
|
||||
if (G_PARAM_SPEC_VALUE_TYPE (prop->pspec) == GTK_TYPE_EXPRESSION)
|
||||
g_value_set_boxed (&property_value, prop->value);
|
||||
else
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
else if (G_IS_PARAM_SPEC_OBJECT (prop->pspec) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (prop->pspec) != GDK_TYPE_PIXBUF) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (prop->pspec) != GDK_TYPE_TEXTURE) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (prop->pspec) != GDK_TYPE_PAINTABLE) &&
|
||||
|
||||
@@ -932,7 +932,7 @@ parse_property (ParserData *data,
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_slice_new (PropertyInfo);
|
||||
info = g_slice_new0 (PropertyInfo);
|
||||
info->tag_type = TAG_PROPERTY;
|
||||
info->pspec = pspec;
|
||||
info->text = g_string_new ("");
|
||||
@@ -948,11 +948,349 @@ parse_property (ParserData *data,
|
||||
static void
|
||||
free_property_info (PropertyInfo *info)
|
||||
{
|
||||
if (info->value)
|
||||
{
|
||||
if (G_PARAM_SPEC_VALUE_TYPE (info->pspec) == GTK_TYPE_EXPRESSION)
|
||||
gtk_expression_unref (info->value);
|
||||
else
|
||||
g_assert_not_reached();
|
||||
}
|
||||
g_string_free (info->text, TRUE);
|
||||
g_free (info->context);
|
||||
g_slice_free (PropertyInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
free_expression_info (ExpressionInfo *info)
|
||||
{
|
||||
switch (info->expression_type)
|
||||
{
|
||||
case EXPRESSION_EXPRESSION:
|
||||
gtk_expression_unref (info->expression);
|
||||
break;
|
||||
|
||||
case EXPRESSION_CONSTANT:
|
||||
g_string_free (info->constant.text, TRUE);
|
||||
break;
|
||||
|
||||
case EXPRESSION_CLOSURE:
|
||||
g_free (info->closure.function_name);
|
||||
g_free (info->closure.object_name);
|
||||
g_slist_free_full (info->closure.params, (GDestroyNotify) free_expression_info);
|
||||
break;
|
||||
|
||||
case EXPRESSION_PROPERTY:
|
||||
g_clear_pointer (&info->property.expression, free_expression_info);
|
||||
g_free (info->property.property_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
g_slice_free (ExpressionInfo, info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_expression_parent (ParserData *data)
|
||||
{
|
||||
CommonInfo *common_info = state_peek_info (data, CommonInfo);
|
||||
|
||||
if (common_info == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (common_info->tag_type == TAG_PROPERTY)
|
||||
{
|
||||
PropertyInfo *prop_info = (PropertyInfo *) common_info;
|
||||
|
||||
return G_PARAM_SPEC_VALUE_TYPE (prop_info->pspec) == GTK_TYPE_EXPRESSION;
|
||||
}
|
||||
|
||||
if (common_info->tag_type == TAG_EXPRESSION)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) common_info;
|
||||
|
||||
switch (expr_info->expression_type)
|
||||
{
|
||||
case EXPRESSION_CLOSURE:
|
||||
return TRUE;
|
||||
case EXPRESSION_CONSTANT:
|
||||
return FALSE;
|
||||
case EXPRESSION_PROPERTY:
|
||||
return expr_info->property.expression == NULL;
|
||||
case EXPRESSION_EXPRESSION:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_constant_expression (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
ExpressionInfo *info;
|
||||
const char *type_name;
|
||||
GType type;
|
||||
|
||||
if (!check_expression_parent (data))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING, "type", &type_name,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
type = gtk_builder_get_type_from_name (data->builder, type_name);
|
||||
if (type == G_TYPE_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Invalid type '%s'", type_name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_slice_new0 (ExpressionInfo);
|
||||
info->tag_type = TAG_EXPRESSION;
|
||||
info->expression_type = EXPRESSION_CONSTANT;
|
||||
info->constant.type = type;
|
||||
info->constant.text = g_string_new (NULL);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_closure_expression (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
ExpressionInfo *info;
|
||||
const char *type_name;
|
||||
const char *function_name;
|
||||
const char *object_name = NULL;
|
||||
gboolean swapped = -1;
|
||||
GType type;
|
||||
|
||||
if (!check_expression_parent (data))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING, "type", &type_name,
|
||||
G_MARKUP_COLLECT_STRING, "function", &function_name,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "object", &object_name,
|
||||
G_MARKUP_COLLECT_TRISTATE|G_MARKUP_COLLECT_OPTIONAL, "swapped", &swapped,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
type = gtk_builder_get_type_from_name (data->builder, type_name);
|
||||
if (type == G_TYPE_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Invalid type '%s'", type_name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Swapped defaults to FALSE except when object is set */
|
||||
if (swapped == -1)
|
||||
{
|
||||
if (object_name)
|
||||
swapped = TRUE;
|
||||
else
|
||||
swapped = FALSE;
|
||||
}
|
||||
|
||||
info = g_slice_new0 (ExpressionInfo);
|
||||
info->tag_type = TAG_EXPRESSION;
|
||||
info->expression_type = EXPRESSION_CLOSURE;
|
||||
info->closure.type = type;
|
||||
info->closure.swapped = swapped;
|
||||
info->closure.function_name = g_strdup (function_name);
|
||||
info->closure.object_name = g_strdup (object_name);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_lookup_expression (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
ExpressionInfo *info;
|
||||
const char *property_name;
|
||||
const char *type_name;
|
||||
GType type;
|
||||
|
||||
if (!check_expression_parent (data))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING, "type", &type_name,
|
||||
G_MARKUP_COLLECT_STRING, "name", &property_name,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
type = gtk_builder_get_type_from_name (data->builder, type_name);
|
||||
if (type == G_TYPE_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Invalid type '%s'", type_name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_slice_new0 (ExpressionInfo);
|
||||
info->tag_type = TAG_EXPRESSION;
|
||||
info->expression_type = EXPRESSION_PROPERTY;
|
||||
info->property.this_type = type;
|
||||
info->property.property_name = g_strdup (property_name);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static GtkExpression *
|
||||
expression_info_construct (GtkBuilder *builder,
|
||||
ExpressionInfo *info,
|
||||
GError **error)
|
||||
{
|
||||
switch (info->expression_type)
|
||||
{
|
||||
case EXPRESSION_EXPRESSION:
|
||||
break;
|
||||
|
||||
case EXPRESSION_CONSTANT:
|
||||
{
|
||||
GtkExpression *expr;
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
if (!gtk_builder_value_from_string_type (builder,
|
||||
info->constant.type,
|
||||
info->constant.text->str,
|
||||
&value,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
if (G_VALUE_HOLDS_OBJECT (&value))
|
||||
expr = gtk_object_expression_new (g_value_get_object (&value));
|
||||
else
|
||||
expr = gtk_constant_expression_new_for_value (&value);
|
||||
g_value_unset (&value);
|
||||
|
||||
g_string_free (info->constant.text, TRUE);
|
||||
info->expression_type = EXPRESSION_EXPRESSION;
|
||||
info->expression = expr;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPRESSION_CLOSURE:
|
||||
{
|
||||
GObject *object;
|
||||
GClosure *closure;
|
||||
guint i, n_params;
|
||||
GtkExpression **params;
|
||||
GtkExpression *expression;
|
||||
GSList *l;
|
||||
|
||||
if (info->closure.object_name)
|
||||
{
|
||||
object = gtk_builder_lookup_object (builder, info->closure.object_name, 0, 0, error);
|
||||
if (object == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
closure = gtk_builder_create_closure (builder,
|
||||
info->closure.function_name,
|
||||
info->closure.swapped,
|
||||
object,
|
||||
error);
|
||||
if (closure == NULL)
|
||||
return NULL;
|
||||
n_params = g_slist_length (info->closure.params);
|
||||
params = g_newa (GtkExpression *, n_params);
|
||||
i = n_params;
|
||||
for (l = info->closure.params; l; l = l->next)
|
||||
{
|
||||
params[--i] = expression_info_construct (builder, l->data, error);
|
||||
if (params[i] == NULL)
|
||||
return NULL;
|
||||
}
|
||||
expression = gtk_closure_expression_new (info->closure.type, closure, n_params, params);
|
||||
g_free (info->closure.function_name);
|
||||
g_free (info->closure.object_name);
|
||||
g_slist_free_full (info->closure.params, (GDestroyNotify) free_expression_info);
|
||||
info->expression_type = EXPRESSION_EXPRESSION;
|
||||
info->expression = expression;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPRESSION_PROPERTY:
|
||||
{
|
||||
GtkExpression *expression;
|
||||
|
||||
if (info->property.expression)
|
||||
{
|
||||
expression = expression_info_construct (builder, info->property.expression, error);
|
||||
if (expression == NULL)
|
||||
return NULL;
|
||||
free_expression_info (info->property.expression);
|
||||
}
|
||||
else
|
||||
expression = NULL;
|
||||
|
||||
expression = gtk_property_expression_new (info->property.this_type,
|
||||
expression,
|
||||
info->property.property_name);
|
||||
g_free (info->property.property_name);
|
||||
info->expression_type = EXPRESSION_EXPRESSION;
|
||||
info->expression = expression;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
return gtk_expression_ref (info->expression);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_signal (ParserData *data,
|
||||
const gchar *element_name,
|
||||
@@ -1287,6 +1625,12 @@ start_element (GtkBuildableParseContext *context,
|
||||
parse_requires (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "interface") == 0)
|
||||
parse_interface (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "constant") == 0)
|
||||
parse_constant_expression (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "closure") == 0)
|
||||
parse_closure_expression (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "lookup") == 0)
|
||||
parse_lookup_expression (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "menu") == 0)
|
||||
_gtk_builder_menu_start (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "placeholder") == 0)
|
||||
@@ -1422,6 +1766,43 @@ end_element (GtkBuildableParseContext *context,
|
||||
signal_info->object_name = g_strdup (object_info->id);
|
||||
object_info->signals = g_slist_prepend (object_info->signals, signal_info);
|
||||
}
|
||||
else if (strcmp (element_name, "constant") == 0 ||
|
||||
strcmp (element_name, "closure") == 0 ||
|
||||
strcmp (element_name, "lookup") == 0)
|
||||
{
|
||||
ExpressionInfo *expression_info = state_pop_info (data, ExpressionInfo);
|
||||
CommonInfo *parent_info = state_peek_info (data, CommonInfo);
|
||||
|
||||
if (parent_info->tag_type == TAG_PROPERTY)
|
||||
{
|
||||
PropertyInfo *prop_info = (PropertyInfo *) parent_info;
|
||||
|
||||
prop_info->value = expression_info_construct (data->builder, expression_info, error);
|
||||
}
|
||||
else if (parent_info->tag_type == TAG_EXPRESSION)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) parent_info;
|
||||
|
||||
switch (expr_info->expression_type)
|
||||
{
|
||||
case EXPRESSION_CLOSURE:
|
||||
expr_info->closure.params = g_slist_prepend (expr_info->closure.params, expression_info);
|
||||
break;
|
||||
case EXPRESSION_PROPERTY:
|
||||
expr_info->property.expression = expression_info;
|
||||
break;
|
||||
case EXPRESSION_EXPRESSION:
|
||||
case EXPRESSION_CONSTANT:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
else if (strcmp (element_name, "requires") == 0)
|
||||
{
|
||||
RequiresInfo *req_info = state_pop_info (data, RequiresInfo);
|
||||
@@ -1502,6 +1883,12 @@ text (GtkBuildableParseContext *context,
|
||||
|
||||
g_string_append_len (prop_info->text, text, text_len);
|
||||
}
|
||||
else if (strcmp (gtk_buildable_parse_context_get_element (context), "constant") == 0)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) info;
|
||||
|
||||
g_string_append_len (expr_info->constant.text, text, text_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1525,6 +1912,9 @@ free_info (CommonInfo *info)
|
||||
case TAG_REQUIRES:
|
||||
free_requires_info ((RequiresInfo *)info, NULL);
|
||||
break;
|
||||
case TAG_EXPRESSION:
|
||||
free_expression_info ((ExpressionInfo *)info);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "gtkbuilder.h"
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkexpression.h"
|
||||
|
||||
enum {
|
||||
TAG_PROPERTY,
|
||||
@@ -31,6 +32,7 @@ enum {
|
||||
TAG_SIGNAL,
|
||||
TAG_INTERFACE,
|
||||
TAG_TEMPLATE,
|
||||
TAG_EXPRESSION,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -64,6 +66,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
guint tag_type;
|
||||
GParamSpec *pspec;
|
||||
gpointer value;
|
||||
GString *text;
|
||||
gboolean translatable:1;
|
||||
gboolean bound:1;
|
||||
@@ -72,6 +75,36 @@ typedef struct {
|
||||
gint col;
|
||||
} PropertyInfo;
|
||||
|
||||
typedef struct _ExpressionInfo ExpressionInfo;
|
||||
struct _ExpressionInfo {
|
||||
guint tag_type;
|
||||
enum {
|
||||
EXPRESSION_EXPRESSION,
|
||||
EXPRESSION_CONSTANT,
|
||||
EXPRESSION_CLOSURE,
|
||||
EXPRESSION_PROPERTY
|
||||
} expression_type;
|
||||
union {
|
||||
GtkExpression *expression;
|
||||
struct {
|
||||
GType type;
|
||||
GString *text;
|
||||
} constant;
|
||||
struct {
|
||||
GType type;
|
||||
char *function_name;
|
||||
char *object_name;
|
||||
gboolean swapped;
|
||||
GSList *params;
|
||||
} closure;
|
||||
struct {
|
||||
GType this_type;
|
||||
char *property_name;
|
||||
ExpressionInfo *expression;
|
||||
} property;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
guint tag_type;
|
||||
gchar *object_name;
|
||||
|
||||
@@ -50,6 +50,44 @@
|
||||
*
|
||||
* Watches can be created for automatically updating the propery of an object,
|
||||
* similar to GObject's #GBinding mechanism, by using gtk_expression_bind().
|
||||
*
|
||||
* #GtkExpression in ui files
|
||||
*
|
||||
* GtkBuilder has support for creating expressions. The syntax here can be used where
|
||||
* a #GtkExpression object is needed like in a <property> tag for an expression
|
||||
* property, or in a <binding> tag to bind a property to an expression.
|
||||
*
|
||||
* To create an property expression, use the <lookup> element. It can have a `type`
|
||||
* attribute to specify the object type, and a `name` attribute to specify the property
|
||||
* to look up. The content of <lookup> can either be an element specfiying the expression
|
||||
* to use the object, or a string that specifies the name of the object to use.
|
||||
*
|
||||
* Example:
|
||||
* |[
|
||||
* <lookup name='search'>string_filter</lookup>
|
||||
* |]
|
||||
*
|
||||
* To create a constant expression, use the <constant> element. If the type attribute
|
||||
* is specified, the element content is interpreted as a value of that type. Otherwise,
|
||||
* it is assumed to be an object.
|
||||
*
|
||||
* Example:
|
||||
* |[
|
||||
* <constant>string_filter</constant>
|
||||
* <constant type='gchararray'>Hello, world</constant>
|
||||
* ]|
|
||||
*
|
||||
* To create a closure expression, use the <closure> element. The `type` and `function`
|
||||
* attributes specify what function to use for the closure, the content of the element
|
||||
* contains the expressions for the parameters.
|
||||
*
|
||||
* Example:
|
||||
* |[
|
||||
* <closure type='gchararray' function='combine_args_somehow'>
|
||||
* <constant type='gchararray'>File size:</constant>
|
||||
* <lookup type='gint64' name='size'>myfile</lookup>
|
||||
* </closure>
|
||||
* ]|
|
||||
*/
|
||||
typedef struct _GtkExpressionClass GtkExpressionClass;
|
||||
|
||||
|
||||
@@ -2643,6 +2643,64 @@ test_file_filter (void)
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
char *
|
||||
builder_get_search (gpointer item)
|
||||
{
|
||||
return g_strdup (gtk_string_filter_get_search (item));
|
||||
}
|
||||
|
||||
char *
|
||||
builder_copy_arg (gpointer item, const char *arg)
|
||||
{
|
||||
return g_strdup (arg);
|
||||
}
|
||||
|
||||
static void
|
||||
test_expressions (void)
|
||||
{
|
||||
const char *tests[] = {
|
||||
"<interface>"
|
||||
" <object class='GtkStringFilter' id='filter'>"
|
||||
" <property name='search'>Hello World</property>"
|
||||
" <property name='expression'><constant type='gchararray'>Hello World</constant></property>"
|
||||
" </object>"
|
||||
"</interface>",
|
||||
"<interface>"
|
||||
" <object class='GtkStringFilter' id='filter'>"
|
||||
" <property name='search'>Hello World</property>"
|
||||
" <property name='expression'><closure type='gchararray' function='builder_get_search'></closure></property>"
|
||||
" </object>"
|
||||
"</interface>",
|
||||
"<interface>"
|
||||
" <object class='GtkStringFilter' id='filter'>"
|
||||
" <property name='search'>Hello World</property>"
|
||||
" <property name='expression'><lookup type='GtkStringFilter' name='search'></lookup></property>"
|
||||
" </object>"
|
||||
"</interface>",
|
||||
"<interface>"
|
||||
" <object class='GtkStringFilter' id='filter'>"
|
||||
" <property name='search'>Hello World</property>"
|
||||
" <property name='expression'><closure type='gchararray' function='builder_copy_arg'>"
|
||||
" <constant type='gchararray'>Hello World</constant>"
|
||||
" </closure></property>"
|
||||
" </object>"
|
||||
"</interface>",
|
||||
};
|
||||
GtkBuilder *builder;
|
||||
GObject *obj;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (tests); i++)
|
||||
{
|
||||
builder = builder_new_from_string (tests[i], -1, NULL);
|
||||
obj = gtk_builder_get_object (builder, "filter");
|
||||
g_assert (GTK_IS_FILTER (obj));
|
||||
g_assert (gtk_filter_match (GTK_FILTER (obj), obj));
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@@ -2695,6 +2753,7 @@ main (int argc, char **argv)
|
||||
g_test_add_func ("/Builder/Property Bindings", test_property_bindings);
|
||||
g_test_add_func ("/Builder/anaconda-signal", test_anaconda_signal);
|
||||
g_test_add_func ("/Builder/FileFilter", test_file_filter);
|
||||
g_test_add_func ("/Builder/Expressions", test_expressions);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user