diff options
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | gladeui/Makefile.am | 1 | ||||
-rw-r--r-- | gladeui/glade-catalog.c | 18 | ||||
-rw-r--r-- | gladeui/glade-catalog.h | 1 | ||||
-rw-r--r-- | gladeui/glade-private.h | 5 | ||||
-rw-r--r-- | gladeui/glade-template.c | 145 | ||||
-rw-r--r-- | gladeui/glade-widget-adaptor.c | 10 | ||||
-rw-r--r-- | gladeui/glade-xml-utils.h | 1 |
8 files changed, 187 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 177508ee..f1e80131 100644 --- a/configure.ac +++ b/configure.ac @@ -168,6 +168,13 @@ AC_CHECK_FUNCS(gtk_print_unix_dialog_new,[have_unix_print=yes]; break,[have_unix AM_CONDITIONAL(HAVE_GTK_UNIX_PRINT, test x"$have_unix_print" = "xyes") dnl ================================================================ +dnl Check for _gtk_widget_class_template_unset_only_for_glade() in gtk+ +dnl ================================================================ +LIBS=$GTK_LIBS +AC_CHECK_FUNCS(_gtk_widget_class_template_unset_only_for_glade,[have_template_unset=yes]; break,[have_template_unset=no]) +AM_CONDITIONAL(HAVE_GTK_TEMPLATE_UNSET, test x"$have_template_unset" = "xyes") + +dnl ================================================================ dnl Python for optional python dev libs dnl ================================================================ PYGOBJECT_REQUIRED_MAJOR=3 diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am index a02d3af3..df8fb9ee 100644 --- a/gladeui/Makefile.am +++ b/gladeui/Makefile.am @@ -125,6 +125,7 @@ libgladeui_2_la_SOURCES = \ glade-signal-class.c \ glade-signal-editor.c \ glade-signal-model.c \ + glade-template.c \ glade-tsort.c \ glade-utils.c \ glade-widget.c \ diff --git a/gladeui/glade-catalog.c b/gladeui/glade-catalog.c index 37366ef5..c1adbe5c 100644 --- a/gladeui/glade-catalog.c +++ b/gladeui/glade-catalog.c @@ -45,6 +45,8 @@ struct _GladeCatalog gchar *name; /* Symbolic catalog name */ + gchar *prefix; /* Catalog path prefix */ + gchar *dep_catalog; /* Symbolic name of the catalog that * this catalog depends on */ @@ -108,6 +110,7 @@ catalog_allocate (void) catalog->library = NULL; catalog->name = NULL; + catalog->prefix = NULL; catalog->dep_catalog = NULL; catalog->domain = NULL; catalog->book = NULL; @@ -201,6 +204,7 @@ catalog_open (const gchar *filename) catalog = catalog_allocate (); catalog->context = context; catalog->name = name; + catalog->prefix = g_path_get_dirname (filename); glade_xml_get_property_version (root, GLADE_TAG_VERSION, &catalog->major_version, @@ -727,6 +731,20 @@ glade_catalog_get_name (GladeCatalog *catalog) } /** + * glade_catalog_get_prefix: + * @catalog: a catalog object + * + * Returns: The catalog path prefix. + */ +G_CONST_RETURN gchar * +glade_catalog_get_prefix (GladeCatalog *catalog) +{ + g_return_val_if_fail (GLADE_IS_CATALOG (catalog), NULL); + + return catalog->prefix; +} + +/** * glade_catalog_get_book: * @catalog: a catalog object * diff --git a/gladeui/glade-catalog.h b/gladeui/glade-catalog.h index 9bf44ba3..efa13dd0 100644 --- a/gladeui/glade-catalog.h +++ b/gladeui/glade-catalog.h @@ -59,6 +59,7 @@ const GList *glade_catalog_get_extra_paths (void); const GList *glade_catalog_load_all (void); G_CONST_RETURN gchar *glade_catalog_get_name (GladeCatalog *catalog); +G_CONST_RETURN gchar *glade_catalog_get_prefix (GladeCatalog *catalog); G_CONST_RETURN gchar *glade_catalog_get_icon_prefix(GladeCatalog *catalog); G_CONST_RETURN gchar *glade_catalog_get_domain (GladeCatalog *catalog); G_CONST_RETURN gchar *glade_catalog_get_book (GladeCatalog *catalog); diff --git a/gladeui/glade-private.h b/gladeui/glade-private.h index 876dc160..a57ab8e8 100644 --- a/gladeui/glade-private.h +++ b/gladeui/glade-private.h @@ -94,6 +94,11 @@ gchar *_glade_util_file_get_relative_path (GFile *target, void _glade_xml_error_reset_last (void); gchar *_glade_xml_error_get_last_message (void); +/* glade-template.c */ +GType _glade_template_generate_type_from_file (GladeCatalog *catalog, + const gchar *parent, + const gchar *filename); + G_END_DECLS #endif /* __GLADE_PRIVATE_H__ */ diff --git a/gladeui/glade-template.c b/gladeui/glade-template.c new file mode 100644 index 00000000..067eeedb --- /dev/null +++ b/gladeui/glade-template.c @@ -0,0 +1,145 @@ +/* + * glade-template.c: + * + * Copyright (C) 2017-2018 Juan Pablo Ugarte. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Authors: + * Juan Pablo Ugarte <juanpablougarte@gmail.com> + */ + +#include "glade-private.h" +#include "glade-utils.h" + +#if HAVE_GTK_TEMPLATE_UNSET +extern void +_gtk_widget_class_template_unset_only_for_glade (GtkWidgetClass *widget_class); +#else +#define _gtk_widget_class_template_unset_only_for_glade(void) +#endif + +static GHashTable *templates = NULL; + +static void +glade_template_instance_init (GTypeInstance *instance, gpointer g_class) +{ + /* Reset class template */ + _gtk_widget_class_template_unset_only_for_glade (GTK_WIDGET_GET_CLASS (instance)); + gtk_widget_class_set_template (GTK_WIDGET_GET_CLASS (instance), + g_hash_table_lookup (templates, + G_OBJECT_TYPE_NAME (instance))); + + /* Regular template initialization*/ + gtk_widget_init_template ((GtkWidget *)instance); +} + +typedef struct { + gchar *class; + gchar *parent; +} ParserData; + +static void +start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParserData *data = user_data; + gint i; + + if (!g_str_equal (element_name, "template")) + return; + + for (i = 0; attribute_names[i]; i++) + if (g_str_equal (attribute_names[i], "class")) + data->class = g_strdup (attribute_values[i]); + else if (g_str_equal (attribute_names[i], "parent")) + data->parent = g_strdup (attribute_values[i]); +} + +GType +_glade_template_generate_type_from_file (GladeCatalog *catalog, + const gchar *name, + const gchar *filename) +{ + GMarkupParser parser = { start_element, NULL, }; + GMarkupParseContext *context; + ParserData data = { 0, }; + GType parent_type; + GTypeQuery query; + GTypeInfo *info; + gchar *template = NULL; + gsize len = 0; + GError *error = NULL; + + g_return_val_if_fail (name != NULL, 0); + g_return_val_if_fail (filename != NULL, 0); + + if (g_path_is_absolute (filename)) + g_file_get_contents (filename, &template, &len, &error); + else + { + gchar *fullpath = g_build_filename (glade_catalog_get_prefix (catalog), + filename, NULL); + g_file_get_contents (fullpath, &template, &len, &error); + g_free (fullpath); + } + + if (error) + { + g_warning ("Error loading template file %s for %s class - %s", filename, name, error->message); + return G_TYPE_INVALID; + } + + context = g_markup_parse_context_new (&parser, 0, &data, NULL); + g_markup_parse_context_parse (context, template, -1, NULL); + g_markup_parse_context_end_parse (context, NULL); + + if (!g_str_equal (name, data.class)) + { + g_warning ("Template %s is for class %s, not %s", filename, data.class, name); + return G_TYPE_INVALID; + } + + parent_type = glade_util_get_type_from_name (data.parent, FALSE); + g_return_val_if_fail (parent_type != 0, 0); + + g_type_query (parent_type, &query); + g_return_val_if_fail (query.type != 0, 0); + + if (g_once_init_enter (&templates)) + { + GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_bytes_unref); + g_once_init_leave (&templates, table); + } + + /* Add template to global hash table */ + g_hash_table_insert (templates, g_strdup (name), g_bytes_new_take (template, len)); + + info = g_new0 (GTypeInfo, 1); + info->class_size = query.class_size; + info->instance_size = query.instance_size; + info->instance_init = glade_template_instance_init; + + g_free (data.class); + g_free (data.parent); + + return g_type_register_static (parent_type, name, info, 0); +} diff --git a/gladeui/glade-widget-adaptor.c b/gladeui/glade-widget-adaptor.c index 17333b4d..fb7babc4 100644 --- a/gladeui/glade-widget-adaptor.c +++ b/gladeui/glade-widget-adaptor.c @@ -2694,7 +2694,7 @@ glade_widget_adaptor_from_catalog (GladeCatalog *catalog, { GladeWidgetAdaptor *adaptor = NULL; gchar *name, *generic_name, *icon_name, *adaptor_icon_name, *adaptor_name, - *func_name; + *func_name, *template; gchar *title, *translated_title, *parent_name; GType object_type, adaptor_type, parent_type; gchar *missing_icon = NULL; @@ -2716,6 +2716,7 @@ glade_widget_adaptor_from_catalog (GladeCatalog *catalog, * - Autosubclassing a specified parent type (a fake widget class) * - parsing the _get_type() function directly from the catalog * - deriving foo_bar_get_type() from the name FooBar and loading that. + * - setting a template ui definition */ if ((parent_name = glade_xml_get_property_string (class_node, GLADE_TAG_PARENT)) != NULL) @@ -2739,6 +2740,13 @@ glade_widget_adaptor_from_catalog (GladeCatalog *catalog, object_type = glade_util_get_type_from_name (func_name, TRUE); g_free (func_name); } + else if ((template = + glade_xml_get_property_string (class_node, + GLADE_XML_TAG_TEMPLATE)) != NULL) + { + object_type = _glade_template_generate_type_from_file (catalog, name, template); + g_free (template); + } else { GType type_iter; diff --git a/gladeui/glade-xml-utils.h b/gladeui/glade-xml-utils.h index 4f2ee706..209cbefd 100644 --- a/gladeui/glade-xml-utils.h +++ b/gladeui/glade-xml-utils.h @@ -185,6 +185,7 @@ typedef struct _GladeProject GladeProject; #define GLADE_TAG_ICON_NAME "icon-name" #define GLADE_TAG_IMPORTANT "important" #define GLADE_TAG_CREATE_TYPE "create-type" +#define GLADE_TAG_TEMPLATE_PREFIX "template-prefix" /* search child */ |