Commit 363fd783 authored by Juan Pablo Ugarte's avatar Juan Pablo Ugarte Committed by Juan Pablo Ugarte

Add initial implementation of Automatic Templates

parent 2ddc72f7
Pipeline #38223 passed with stages
in 12 minutes and 8 seconds
......@@ -167,6 +167,13 @@ LIBS=$GTK_LIBS
AC_CHECK_FUNCS(gtk_print_unix_dialog_new,[have_unix_print=yes]; break,[have_unix_print=no])
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 ================================================================
......
......@@ -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 \
......
......@@ -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,
......@@ -726,6 +730,20 @@ glade_catalog_get_name (GladeCatalog *catalog)
return catalog->name;
}
/**
* 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
......
......@@ -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);
......
......@@ -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__ */
/*
* 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);
}
......@@ -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;
......
......@@ -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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment