mirror of
https://gitlab.gnome.org/GNOME/glade.git
synced 2025-10-17 00:08:25 -04:00
Added intitial support for runtime creation and loading of composite templates.
gladeui/glade-app.c: Load composite templates from G_USER_DIRECTORY_TEMPLATES gladeui/glade-project.[ch] o Added glade_project_dump_string() o Addes safe guards for NULL catalogs (composite template adaptors does not have a catalog) gladeui/glade-widget-adaptor.[ch] o Added template and template-path properties o Added glade_widget_adaptor_get_template() and glade_widget_adaptor_from_composite_template() gladeui/glade-composite-template.[ch]: Added support to load composite templates and export a widget as such. plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: added "Export as template" action
This commit is contained in:
parent
451dd4024f
commit
856a93ad0e
@ -53,6 +53,7 @@ libgladeui_2_la_SOURCES = \
|
|||||||
glade-object-stub.c \
|
glade-object-stub.c \
|
||||||
glade-xml-utils.c \
|
glade-xml-utils.c \
|
||||||
glade-catalog.c \
|
glade-catalog.c \
|
||||||
|
glade-composite-template.c \
|
||||||
glade-widget-adaptor.c \
|
glade-widget-adaptor.c \
|
||||||
glade-widget.c \
|
glade-widget.c \
|
||||||
glade-property-class.c \
|
glade-property-class.c \
|
||||||
@ -122,6 +123,7 @@ libgladeuiinclude_HEADERS = \
|
|||||||
glade-design-view.h \
|
glade-design-view.h \
|
||||||
glade-widget.h \
|
glade-widget.h \
|
||||||
glade-widget-adaptor.h \
|
glade-widget-adaptor.h \
|
||||||
|
glade-composite-template.h \
|
||||||
glade-property.h \
|
glade-property.h \
|
||||||
glade-property-class.h \
|
glade-property-class.h \
|
||||||
glade-utils.h \
|
glade-utils.h \
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "glade-design-layout.h"
|
#include "glade-design-layout.h"
|
||||||
#include "glade-marshallers.h"
|
#include "glade-marshallers.h"
|
||||||
#include "glade-accumulators.h"
|
#include "glade-accumulators.h"
|
||||||
|
#include "glade-composite-template.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
@ -348,6 +349,8 @@ glade_app_init (GladeApp *app)
|
|||||||
|
|
||||||
/* Load the configuration file */
|
/* Load the configuration file */
|
||||||
priv->config = g_key_file_ref (glade_app_get_config ());
|
priv->config = g_key_file_ref (glade_app_get_config ());
|
||||||
|
|
||||||
|
glade_composite_template_load_directory (g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
260
gladeui/glade-composite-template.c
Normal file
260
gladeui/glade-composite-template.c
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* glade-composite-template.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Juan Pablo Ugarte
|
||||||
|
*
|
||||||
|
* Author: Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "glade-composite-template.h"
|
||||||
|
#include "glade-app.h"
|
||||||
|
#include "glade-utils.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gboolean right_id;
|
||||||
|
GType parent;
|
||||||
|
const gchar *type_name;
|
||||||
|
} ParseData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_element (GMarkupParseContext *context,
|
||||||
|
const gchar *element_name,
|
||||||
|
const gchar **attribute_names,
|
||||||
|
const gchar **attribute_values,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ParseData *state = user_data;
|
||||||
|
|
||||||
|
if (g_strcmp0 (element_name, "template") == 0)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; attribute_names[i]; i++)
|
||||||
|
{
|
||||||
|
if (!g_strcmp0 (attribute_names[i], "parent"))
|
||||||
|
state->parent = glade_util_get_type_from_name (attribute_values[i], FALSE);
|
||||||
|
else if (!g_strcmp0 (attribute_names[i], "class"))
|
||||||
|
state->type_name = g_intern_string (attribute_values[i]);
|
||||||
|
else if (!g_strcmp0 (attribute_names[i], "id"))
|
||||||
|
state->right_id = (g_strcmp0 (attribute_values[i], "this") == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_template (const gchar *template_str, GType *parent, const gchar **type_name)
|
||||||
|
{
|
||||||
|
GMarkupParser parser = { start_element };
|
||||||
|
ParseData state = { FALSE, G_TYPE_INVALID, NULL };
|
||||||
|
GMarkupParseContext *context;
|
||||||
|
|
||||||
|
context = g_markup_parse_context_new (&parser,
|
||||||
|
G_MARKUP_TREAT_CDATA_AS_TEXT |
|
||||||
|
G_MARKUP_PREFIX_ERROR_POSITION,
|
||||||
|
&state, NULL);
|
||||||
|
|
||||||
|
g_markup_parse_context_parse (context, template_str, -1, NULL);
|
||||||
|
g_markup_parse_context_end_parse (context, NULL);
|
||||||
|
g_markup_parse_context_free (context);
|
||||||
|
|
||||||
|
if (!g_type_is_a (state.parent, GTK_TYPE_CONTAINER))
|
||||||
|
{
|
||||||
|
g_warning ("Composite templates should derive from GtkContainer");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent) *parent = state.parent;
|
||||||
|
if (type_name) *type_name = state.type_name;
|
||||||
|
|
||||||
|
return state.right_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
composite_template_derived_init (GTypeInstance *instance, gpointer g_class)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
composite_template_derived_class_init (gpointer g_class, gpointer class_data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GType
|
||||||
|
generate_type (GType parent, const gchar *type_name)
|
||||||
|
{
|
||||||
|
GTypeQuery query;
|
||||||
|
|
||||||
|
g_type_query (parent, &query);
|
||||||
|
|
||||||
|
return g_type_register_static_simple (parent, type_name,
|
||||||
|
query.class_size,
|
||||||
|
composite_template_derived_class_init,
|
||||||
|
query.instance_size,
|
||||||
|
composite_template_derived_init,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public API */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* glade_composite_template_load_from_string:
|
||||||
|
* @template_xml: a #GtkBuilder UI description string
|
||||||
|
*
|
||||||
|
* This function will create a new GType from the template UI description defined
|
||||||
|
* by @template_xml and its corresponding #GladeWidgetAdator
|
||||||
|
*
|
||||||
|
* Returns: A newlly created and registered #GladeWidgetAdptor or NULL if @template_xml is malformed.
|
||||||
|
*/
|
||||||
|
GladeWidgetAdaptor *
|
||||||
|
glade_composite_template_load_from_string (const gchar *template_xml)
|
||||||
|
{
|
||||||
|
const gchar *type_name = NULL;
|
||||||
|
GType parent;
|
||||||
|
|
||||||
|
g_return_val_if_fail (template_xml != NULL, NULL);
|
||||||
|
|
||||||
|
if (parse_template (template_xml, &parent, &type_name))
|
||||||
|
{
|
||||||
|
GladeWidgetAdaptor *adaptor;
|
||||||
|
GType template_type;
|
||||||
|
|
||||||
|
/* Generate dummy template type */
|
||||||
|
template_type = generate_type (parent, type_name);
|
||||||
|
|
||||||
|
/* Create adaptor for template */
|
||||||
|
adaptor = glade_widget_adaptor_from_composite_template (template_type,
|
||||||
|
template_xml,
|
||||||
|
type_name,
|
||||||
|
NULL); /* TODO: generate icon name from parent icon plus some emblem */
|
||||||
|
/* Register adaptor */
|
||||||
|
glade_widget_adaptor_register (adaptor);
|
||||||
|
|
||||||
|
return adaptor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_warning ("Could not parse template");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* glade_composite_template_load_from_file:
|
||||||
|
* @path: a filename to load
|
||||||
|
*
|
||||||
|
* Loads a composite template from a file.
|
||||||
|
* See glade_composite_template_load_from_string() for details.
|
||||||
|
*
|
||||||
|
* Returns: A newlly created and registered #GladeWidgetAdaptor or NULL.
|
||||||
|
*/
|
||||||
|
GladeWidgetAdaptor *
|
||||||
|
glade_composite_template_load_from_file (const gchar *path)
|
||||||
|
{
|
||||||
|
GladeWidgetAdaptor *adaptor;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *contents;
|
||||||
|
|
||||||
|
g_return_val_if_fail (path != NULL, NULL);
|
||||||
|
|
||||||
|
if (!g_file_get_contents (path, &contents, NULL, &error))
|
||||||
|
{
|
||||||
|
g_warning ("Could not load template `%s` %s", path, error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((adaptor = glade_composite_template_load_from_string (contents)))
|
||||||
|
g_object_set (adaptor, "template-path", path, NULL);
|
||||||
|
|
||||||
|
g_free (contents);
|
||||||
|
|
||||||
|
return adaptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* glade_composite_template_load_directory:
|
||||||
|
* @directory: a directory path.
|
||||||
|
*
|
||||||
|
* Loads every .ui composite template found in @directory
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
glade_composite_template_load_directory (const gchar *directory)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
const gchar *name;
|
||||||
|
GDir *dir;
|
||||||
|
|
||||||
|
g_return_if_fail (path != NULL);
|
||||||
|
|
||||||
|
if (!(dir = g_dir_open (directory, 0, &error)))
|
||||||
|
{
|
||||||
|
g_warning ("Could not open directory `%s` %s", directory, error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((name = g_dir_read_name (dir)))
|
||||||
|
{
|
||||||
|
if (g_str_has_suffix (name, ".ui"))
|
||||||
|
{
|
||||||
|
gchar *fullname = g_build_filename (directory, name, NULL);
|
||||||
|
glade_composite_template_load_from_file (fullname);
|
||||||
|
g_free (fullname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close (dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* glade_composite_template_save_from_widget:
|
||||||
|
* @gwidget: a #GladeWidget
|
||||||
|
* @template_class: the name of the new composite template class
|
||||||
|
* @filename: a file name to save the template
|
||||||
|
*
|
||||||
|
* Saves a copy of @gwidget as a composite template in @filename with @template_class
|
||||||
|
* as the class name
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
glade_composite_template_save_from_widget (GladeWidget *gwidget,
|
||||||
|
const gchar *template_class,
|
||||||
|
const gchar *filename)
|
||||||
|
{
|
||||||
|
GladeProject *project;
|
||||||
|
gchar *template_xml;
|
||||||
|
GladeWidget *dup;
|
||||||
|
|
||||||
|
g_return_if_fail (GLADE_IS_WIDGET (gwidget));
|
||||||
|
g_return_if_fail (template_class && filename);
|
||||||
|
g_return_if_fail (GTK_IS_CONTAINER (glade_widget_get_object (gwidget)));
|
||||||
|
|
||||||
|
project = glade_project_new ();
|
||||||
|
dup = glade_widget_dup (gwidget, TRUE);
|
||||||
|
|
||||||
|
/* make dupped widget a template */
|
||||||
|
glade_widget_set_name (dup, "this");
|
||||||
|
glade_widget_set_template_class (dup, template_class);
|
||||||
|
|
||||||
|
glade_project_add_object (project, glade_widget_get_object (dup));
|
||||||
|
template_xml = glade_project_dump_string (project);
|
||||||
|
|
||||||
|
g_file_set_contents (filename, template_xml, -1, NULL);
|
||||||
|
|
||||||
|
g_free (template_xml);
|
||||||
|
g_object_unref (project);
|
||||||
|
}
|
42
gladeui/glade-composite-template.h
Normal file
42
gladeui/glade-composite-template.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* glade-composite-template.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Juan Pablo Ugarte
|
||||||
|
*
|
||||||
|
* Author: Juan Pablo Ugarte <juanpablougarte@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GLADE_COMPOSITE_TEMPLATE_H__
|
||||||
|
#define __GLADE_COMPOSITE_TEMPLATE_H__
|
||||||
|
|
||||||
|
#include <gladeui/glade-widget.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
GladeWidgetAdaptor *glade_composite_template_load_from_string (const gchar *template_xml);
|
||||||
|
|
||||||
|
GladeWidgetAdaptor *glade_composite_template_load_from_file (const gchar *path);
|
||||||
|
|
||||||
|
void glade_composite_template_load_directory (const gchar *directory);
|
||||||
|
|
||||||
|
void glade_composite_template_save_from_widget (GladeWidget *gwidget,
|
||||||
|
const gchar *template_class,
|
||||||
|
const gchar *filename);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GLADE_COMPOSITE_TEMPLATE_H__ */
|
@ -1993,6 +1993,25 @@ glade_project_save (GladeProject *project, const gchar *path, GError **error)
|
|||||||
return ret > 0;
|
return ret > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* glade_project_dump_string:
|
||||||
|
* @project: a #GladeProject
|
||||||
|
*
|
||||||
|
* Returns: @project as a newlly allocated string
|
||||||
|
*/
|
||||||
|
gchar *
|
||||||
|
glade_project_dump_string (GladeProject *project)
|
||||||
|
{
|
||||||
|
GladeXmlContext *context;
|
||||||
|
gchar *retval;
|
||||||
|
|
||||||
|
context = glade_project_write (project);
|
||||||
|
retval = glade_xml_dump_from_context (context);
|
||||||
|
glade_xml_context_destroy (context);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* glade_project_preview:
|
* glade_project_preview:
|
||||||
* @project: a #GladeProject
|
* @project: a #GladeProject
|
||||||
@ -2122,6 +2141,13 @@ glade_project_verify_property_internal (GladeProject *project,
|
|||||||
adaptor = glade_widget_adaptor_from_pspec (prop_adaptor, pspec);
|
adaptor = glade_widget_adaptor_from_pspec (prop_adaptor, pspec);
|
||||||
|
|
||||||
g_object_get (adaptor, "catalog", &catalog, NULL);
|
g_object_get (adaptor, "catalog", &catalog, NULL);
|
||||||
|
|
||||||
|
/* no need to check if there is no catalog because its a composite widget
|
||||||
|
* automagically loaded by libgladeui
|
||||||
|
*/
|
||||||
|
if (catalog == NULL && glade_widget_adaptor_get_template (adaptor))
|
||||||
|
return;
|
||||||
|
|
||||||
glade_project_target_version_for_adaptor (project, adaptor,
|
glade_project_target_version_for_adaptor (project, adaptor,
|
||||||
&target_major, &target_minor);
|
&target_major, &target_minor);
|
||||||
|
|
||||||
@ -2207,6 +2233,10 @@ glade_project_verify_signal_internal (GladeWidget *widget,
|
|||||||
adaptor = glade_signal_class_get_adaptor (signal_class);
|
adaptor = glade_signal_class_get_adaptor (signal_class);
|
||||||
|
|
||||||
g_object_get (adaptor, "catalog", &catalog, NULL);
|
g_object_get (adaptor, "catalog", &catalog, NULL);
|
||||||
|
|
||||||
|
if (catalog == NULL && glade_widget_adaptor_get_template (adaptor))
|
||||||
|
return;
|
||||||
|
|
||||||
glade_project_target_version_for_adaptor (glade_widget_get_project (widget),
|
glade_project_target_version_for_adaptor (glade_widget_get_project (widget),
|
||||||
adaptor,
|
adaptor,
|
||||||
&target_major, &target_minor);
|
&target_major, &target_minor);
|
||||||
@ -2427,8 +2457,11 @@ glade_project_verify_adaptor (GladeProject *project,
|
|||||||
for (adaptor_iter = adaptor; adaptor_iter && support_mask == GLADE_SUPPORT_OK;
|
for (adaptor_iter = adaptor; adaptor_iter && support_mask == GLADE_SUPPORT_OK;
|
||||||
adaptor_iter = glade_widget_adaptor_get_parent_adaptor (adaptor_iter))
|
adaptor_iter = glade_widget_adaptor_get_parent_adaptor (adaptor_iter))
|
||||||
{
|
{
|
||||||
|
|
||||||
g_object_get (adaptor_iter, "catalog", &catalog, NULL);
|
g_object_get (adaptor_iter, "catalog", &catalog, NULL);
|
||||||
|
|
||||||
|
if (catalog == NULL && glade_widget_adaptor_get_template (adaptor))
|
||||||
|
continue;
|
||||||
|
|
||||||
glade_project_target_version_for_adaptor (project, adaptor_iter,
|
glade_project_target_version_for_adaptor (project, adaptor_iter,
|
||||||
&target_major, &target_minor);
|
&target_major, &target_minor);
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ gboolean glade_project_load_from_file (GladeProject *proj
|
|||||||
gboolean glade_project_save (GladeProject *project,
|
gboolean glade_project_save (GladeProject *project,
|
||||||
const gchar *path,
|
const gchar *path,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
gchar *glade_project_dump_string (GladeProject *project);
|
||||||
void glade_project_push_progress (GladeProject *project);
|
void glade_project_push_progress (GladeProject *project);
|
||||||
gboolean glade_project_load_cancelled (GladeProject *project);
|
gboolean glade_project_load_cancelled (GladeProject *project);
|
||||||
void glade_project_cancel_load (GladeProject *project);
|
void glade_project_cancel_load (GladeProject *project);
|
||||||
|
@ -102,6 +102,8 @@ struct _GladeWidgetAdaptorPrivate
|
|||||||
* are special children (like notebook tab
|
* are special children (like notebook tab
|
||||||
* widgets for example).
|
* widgets for example).
|
||||||
*/
|
*/
|
||||||
|
gchar *template_xml; /* The GtkBuilder template if this is a composite template class */
|
||||||
|
GFileMonitor *template_monitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GladeChildPacking
|
struct _GladeChildPacking
|
||||||
@ -135,7 +137,9 @@ enum
|
|||||||
PROP_CATALOG,
|
PROP_CATALOG,
|
||||||
PROP_BOOK,
|
PROP_BOOK,
|
||||||
PROP_SPECIAL_TYPE,
|
PROP_SPECIAL_TYPE,
|
||||||
PROP_CURSOR
|
PROP_CURSOR,
|
||||||
|
PROP_TEMPLATE,
|
||||||
|
PROP_TEMPLATE_PATH
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _GladeChildPacking GladeChildPacking;
|
typedef struct _GladeChildPacking GladeChildPacking;
|
||||||
@ -380,7 +384,7 @@ gwa_clone_parent_properties (GladeWidgetAdaptor *adaptor, gboolean is_packing)
|
|||||||
parent_adaptor->priv->packing_props : parent_adaptor->priv->properties;
|
parent_adaptor->priv->packing_props : parent_adaptor->priv->properties;
|
||||||
|
|
||||||
/* Reset versioning in derived catalogs just once */
|
/* Reset versioning in derived catalogs just once */
|
||||||
reset_version = strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog) != 0;
|
reset_version = g_strcmp0 (adaptor->priv->catalog, parent_adaptor->priv->catalog) != 0;
|
||||||
|
|
||||||
for (list = proplist; list; list = list->next)
|
for (list = proplist; list; list = list->next)
|
||||||
{
|
{
|
||||||
@ -533,8 +537,8 @@ gwa_inherit_signals (GladeWidgetAdaptor *adaptor)
|
|||||||
parent_signal = node->data;
|
parent_signal = node->data;
|
||||||
|
|
||||||
/* Reset versioning in derived catalogs just once */
|
/* Reset versioning in derived catalogs just once */
|
||||||
if (strcmp (adaptor->priv->catalog,
|
if (g_strcmp0 (adaptor->priv->catalog,
|
||||||
parent_adaptor->priv->catalog))
|
parent_adaptor->priv->catalog))
|
||||||
glade_signal_class_set_since (signal, 0, 0);
|
glade_signal_class_set_since (signal, 0, 0);
|
||||||
else
|
else
|
||||||
glade_signal_class_set_since (signal,
|
glade_signal_class_set_since (signal,
|
||||||
@ -624,7 +628,7 @@ glade_widget_adaptor_constructor (GType type,
|
|||||||
|
|
||||||
/* Reset version numbering if we're in a new catalog just once */
|
/* Reset version numbering if we're in a new catalog just once */
|
||||||
if (parent_adaptor &&
|
if (parent_adaptor &&
|
||||||
strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog))
|
g_strcmp0 (adaptor->priv->catalog, parent_adaptor->priv->catalog))
|
||||||
{
|
{
|
||||||
GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_major =
|
GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_major =
|
||||||
GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_minor = 0;
|
GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_minor = 0;
|
||||||
@ -711,59 +715,48 @@ static void
|
|||||||
glade_widget_adaptor_finalize (GObject *object)
|
glade_widget_adaptor_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
GladeWidgetAdaptor *adaptor = GLADE_WIDGET_ADAPTOR (object);
|
GladeWidgetAdaptor *adaptor = GLADE_WIDGET_ADAPTOR (object);
|
||||||
|
GladeWidgetAdaptorPrivate *priv = adaptor->priv;
|
||||||
|
|
||||||
/* Free properties and signals */
|
/* Free properties and signals */
|
||||||
g_list_foreach (adaptor->priv->properties, (GFunc) glade_property_class_free, NULL);
|
g_list_foreach (priv->properties, (GFunc) glade_property_class_free, NULL);
|
||||||
g_list_free (adaptor->priv->properties);
|
g_list_free (priv->properties);
|
||||||
|
|
||||||
g_list_foreach (adaptor->priv->packing_props, (GFunc) glade_property_class_free,
|
g_list_foreach (priv->packing_props, (GFunc) glade_property_class_free,
|
||||||
NULL);
|
NULL);
|
||||||
g_list_free (adaptor->priv->packing_props);
|
g_list_free (priv->packing_props);
|
||||||
|
|
||||||
/* Be careful, this list holds GladeSignalClass* not GladeSignal,
|
/* Be careful, this list holds GladeSignalClass* not GladeSignal,
|
||||||
* thus g_free is enough as all members are const */
|
* thus g_free is enough as all members are const */
|
||||||
g_list_foreach (adaptor->priv->signals, (GFunc) g_free, NULL);
|
g_list_foreach (priv->signals, (GFunc) g_free, NULL);
|
||||||
g_list_free (adaptor->priv->signals);
|
g_list_free (priv->signals);
|
||||||
|
|
||||||
|
|
||||||
/* Free child packings */
|
/* Free child packings */
|
||||||
g_list_foreach (adaptor->priv->child_packings,
|
g_list_foreach (priv->child_packings, (GFunc) gwa_child_packing_free, NULL);
|
||||||
(GFunc) gwa_child_packing_free, NULL);
|
g_list_free (priv->child_packings);
|
||||||
g_list_free (adaptor->priv->child_packings);
|
|
||||||
|
|
||||||
if (adaptor->priv->book)
|
g_free (priv->book);
|
||||||
g_free (adaptor->priv->book);
|
g_free (priv->catalog);
|
||||||
if (adaptor->priv->catalog)
|
g_free (priv->special_child_type);
|
||||||
g_free (adaptor->priv->catalog);
|
g_clear_object (&priv->cursor);
|
||||||
if (adaptor->priv->special_child_type)
|
g_free (priv->name);
|
||||||
g_free (adaptor->priv->special_child_type);
|
g_free (priv->generic_name);
|
||||||
|
g_free (priv->title);
|
||||||
|
g_free (priv->icon_name);
|
||||||
|
g_free (priv->missing_icon);
|
||||||
|
g_free (priv->template_xml);
|
||||||
|
|
||||||
if (adaptor->priv->cursor != NULL)
|
if (priv->actions)
|
||||||
g_object_unref (adaptor->priv->cursor);
|
|
||||||
|
|
||||||
if (adaptor->priv->name)
|
|
||||||
g_free (adaptor->priv->name);
|
|
||||||
if (adaptor->priv->generic_name)
|
|
||||||
g_free (adaptor->priv->generic_name);
|
|
||||||
if (adaptor->priv->title)
|
|
||||||
g_free (adaptor->priv->title);
|
|
||||||
if (adaptor->priv->icon_name)
|
|
||||||
g_free (adaptor->priv->icon_name);
|
|
||||||
if (adaptor->priv->missing_icon)
|
|
||||||
g_free (adaptor->priv->missing_icon);
|
|
||||||
|
|
||||||
if (adaptor->priv->actions)
|
|
||||||
{
|
{
|
||||||
g_list_foreach (adaptor->priv->actions,
|
g_list_foreach (priv->actions,
|
||||||
(GFunc) glade_widget_action_class_free, NULL);
|
(GFunc) glade_widget_action_class_free, NULL);
|
||||||
g_list_free (adaptor->priv->actions);
|
g_list_free (priv->actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adaptor->priv->packing_actions)
|
if (priv->packing_actions)
|
||||||
{
|
{
|
||||||
g_list_foreach (adaptor->priv->packing_actions,
|
g_list_foreach (priv->packing_actions,
|
||||||
(GFunc) glade_widget_action_class_free, NULL);
|
(GFunc) glade_widget_action_class_free, NULL);
|
||||||
g_list_free (adaptor->priv->packing_actions);
|
g_list_free (priv->packing_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
gwa_internal_children_free (adaptor);
|
gwa_internal_children_free (adaptor);
|
||||||
@ -771,6 +764,103 @@ glade_widget_adaptor_finalize (GObject *object)
|
|||||||
G_OBJECT_CLASS (glade_widget_adaptor_parent_class)->finalize (object);
|
G_OBJECT_CLASS (glade_widget_adaptor_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gwa_template_rebuild_objects (GladeWidgetAdaptor *adaptor, GType object_type)
|
||||||
|
{
|
||||||
|
GList *l, *rebuild = NULL;
|
||||||
|
|
||||||
|
/* Iterate all projects */
|
||||||
|
for (l = glade_app_get_projects (); l; l = g_list_next (l))
|
||||||
|
{
|
||||||
|
GladeProject *project = l->data;
|
||||||
|
const GList *o;
|
||||||
|
|
||||||
|
/* Iterate all objects in the project */
|
||||||
|
for (o = glade_project_get_objects (project); o; o = g_list_next (o))
|
||||||
|
{
|
||||||
|
GObject *obj = o->data;
|
||||||
|
|
||||||
|
/* And rebuild widget if its template just changed */
|
||||||
|
if (g_type_is_a (G_OBJECT_TYPE (obj), object_type))
|
||||||
|
rebuild = g_list_prepend (rebuild, glade_widget_get_from_gobject (obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (l = rebuild; l; l = g_list_next (l))
|
||||||
|
glade_widget_rebuild (l->data);
|
||||||
|
|
||||||
|
g_list_free (rebuild);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
glade_widget_adaptor_set_template (GladeWidgetAdaptor *adaptor,
|
||||||
|
const gchar *template_xml)
|
||||||
|
{
|
||||||
|
GladeWidgetAdaptorPrivate *priv = adaptor->priv;
|
||||||
|
GtkContainerClass *klass;
|
||||||
|
GType object_type;
|
||||||
|
|
||||||
|
if (g_strcmp0 (priv->template_xml, template_xml) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free (priv->template_xml);
|
||||||
|
priv->template_xml = g_strdup (template_xml);
|
||||||
|
|
||||||
|
/* Update container class template */
|
||||||
|
object_type = glade_widget_adaptor_get_object_type (adaptor);
|
||||||
|
klass = g_type_class_peek (object_type);
|
||||||
|
gtk_container_class_set_template_from_string (klass, priv->template_xml);
|
||||||
|
gwa_template_rebuild_objects (adaptor, object_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_template_file_changed (GFileMonitor *monitor,
|
||||||
|
GFile *file,
|
||||||
|
GFile *other_file,
|
||||||
|
GFileMonitorEvent event_type,
|
||||||
|
GladeWidgetAdaptor *adaptor)
|
||||||
|
{
|
||||||
|
gchar *contents = NULL;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_file_load_contents (file, NULL, &contents, &len, NULL, NULL))
|
||||||
|
{
|
||||||
|
g_object_set (adaptor, "template", contents, NULL);
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
glade_widget_adaptor_set_template_path (GladeWidgetAdaptor *adaptor,
|
||||||
|
const gchar *path)
|
||||||
|
{
|
||||||
|
GladeWidgetAdaptorPrivate *priv = adaptor->priv;
|
||||||
|
GFile *file = g_file_new_for_path (path);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_clear_object (&priv->template_monitor);
|
||||||
|
|
||||||
|
/* Add watch for file */
|
||||||
|
priv->template_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
|
||||||
|
|
||||||
|
if (priv->template_monitor)
|
||||||
|
{
|
||||||
|
g_signal_connect (priv->template_monitor, "changed",
|
||||||
|
G_CALLBACK (on_template_file_changed),
|
||||||
|
adaptor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("Unable to monitor path `%s` %s", path, error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (file);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glade_widget_adaptor_real_set_property (GObject *object,
|
glade_widget_adaptor_real_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -820,6 +910,12 @@ glade_widget_adaptor_real_set_property (GObject *object,
|
|||||||
g_free (adaptor->priv->special_child_type);
|
g_free (adaptor->priv->special_child_type);
|
||||||
adaptor->priv->special_child_type = g_value_dup_string (value);
|
adaptor->priv->special_child_type = g_value_dup_string (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TEMPLATE:
|
||||||
|
glade_widget_adaptor_set_template (adaptor, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_TEMPLATE_PATH:
|
||||||
|
glade_widget_adaptor_set_template_path (adaptor, g_value_get_string (value));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -866,6 +962,9 @@ glade_widget_adaptor_real_get_property (GObject *object,
|
|||||||
case PROP_CURSOR:
|
case PROP_CURSOR:
|
||||||
g_value_set_pointer (value, adaptor->priv->cursor);
|
g_value_set_pointer (value, adaptor->priv->cursor);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TEMPLATE:
|
||||||
|
g_value_set_string (value, adaptor->priv->template_xml);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -1455,6 +1554,20 @@ glade_widget_adaptor_class_init (GladeWidgetAdaptorClass *adaptor_class)
|
|||||||
("cursor", _("Cursor"),
|
("cursor", _("Cursor"),
|
||||||
_("A cursor for inserting widgets in the UI"), G_PARAM_READABLE));
|
_("A cursor for inserting widgets in the UI"), G_PARAM_READABLE));
|
||||||
|
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class, PROP_TEMPLATE,
|
||||||
|
g_param_spec_string
|
||||||
|
("template", _("Template"),
|
||||||
|
_("Builder template of the class"),
|
||||||
|
NULL, G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class, PROP_TEMPLATE_PATH,
|
||||||
|
g_param_spec_string
|
||||||
|
("template-path", _("Template path"),
|
||||||
|
_("Builder template file path of the class, if set it will be used to monitor and update template property automatically"),
|
||||||
|
NULL, G_PARAM_WRITABLE));
|
||||||
|
|
||||||
g_type_class_add_private (adaptor_class, sizeof (GladeWidgetAdaptorPrivate));
|
g_type_class_add_private (adaptor_class, sizeof (GladeWidgetAdaptorPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1632,8 +1745,13 @@ static void
|
|||||||
gwa_derived_class_init (GladeWidgetAdaptorClass *adaptor_class,
|
gwa_derived_class_init (GladeWidgetAdaptorClass *adaptor_class,
|
||||||
GWADerivedClassData *data)
|
GWADerivedClassData *data)
|
||||||
{
|
{
|
||||||
GladeXmlNode *node = data->node;
|
GladeXmlNode *node;
|
||||||
GModule *module = data->module;
|
GModule *module;
|
||||||
|
|
||||||
|
if (data == NULL) return;
|
||||||
|
|
||||||
|
node = data->node;
|
||||||
|
module = data->module;
|
||||||
|
|
||||||
/* Load catalog symbols from module */
|
/* Load catalog symbols from module */
|
||||||
if (module)
|
if (module)
|
||||||
@ -1705,7 +1823,6 @@ gwa_derive_adaptor_for_type (GType object_type, GWADerivedClassData *data)
|
|||||||
return derived_type;
|
return derived_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
API
|
API
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -1781,6 +1898,14 @@ glade_widget_adaptor_get_signals (GladeWidgetAdaptor *adaptor)
|
|||||||
return adaptor->priv->signals;
|
return adaptor->priv->signals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_CONST_RETURN gchar *
|
||||||
|
glade_widget_adaptor_get_template (GladeWidgetAdaptor *adaptor)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
|
||||||
|
|
||||||
|
return adaptor->priv->template_xml;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
accum_adaptor (GType *type, GladeWidgetAdaptor *adaptor, GList **list)
|
accum_adaptor (GType *type, GladeWidgetAdaptor *adaptor, GList **list)
|
||||||
{
|
{
|
||||||
@ -2600,6 +2725,54 @@ generate_deprecated_icon (const gchar *icon_name)
|
|||||||
return deprecated;
|
return deprecated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* glade_widget_adaptor_from_composite_template:
|
||||||
|
* @template_type: a #GType
|
||||||
|
* @template_xml: composite template ui description
|
||||||
|
* @generic_name: the genereic name of the adaptor
|
||||||
|
* @icon_name: the icon name for the adaptor or NULL to fallback to the parent
|
||||||
|
*
|
||||||
|
* Dynamicaly creates the corresponding adaptor for the template type.
|
||||||
|
*/
|
||||||
|
GladeWidgetAdaptor *
|
||||||
|
glade_widget_adaptor_from_composite_template (GType template_type,
|
||||||
|
const gchar *template_xml,
|
||||||
|
const gchar *generic_name,
|
||||||
|
const gchar *icon_name)
|
||||||
|
{
|
||||||
|
gchar *adaptor_icon_name = NULL;
|
||||||
|
GladeWidgetAdaptor *adaptor;
|
||||||
|
GType adaptor_type;
|
||||||
|
const gchar *name;
|
||||||
|
|
||||||
|
g_return_val_if_fail (g_type_is_a (template_type, GTK_TYPE_CONTAINER), NULL);
|
||||||
|
|
||||||
|
adaptor_type = gwa_derive_adaptor_for_type (template_type, NULL);
|
||||||
|
name = g_type_name (template_type);
|
||||||
|
|
||||||
|
/* Fallback to parent icon */
|
||||||
|
if (!icon_name)
|
||||||
|
{
|
||||||
|
GladeWidgetAdaptor *parent = glade_widget_adaptor_get_parent_adaptor_by_type (template_type);
|
||||||
|
adaptor_icon_name = g_strdup ((parent && parent->priv->icon_name) ?
|
||||||
|
parent->priv->icon_name : DEFAULT_ICON_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
adaptor = g_object_new (adaptor_type,
|
||||||
|
"type", template_type,
|
||||||
|
"template", template_xml,
|
||||||
|
"name", name,
|
||||||
|
"catalog", NULL, /* yup NULL, it does not have a catalog */
|
||||||
|
"generic-name", generic_name,
|
||||||
|
"icon-name", icon_name ? icon_name : adaptor_icon_name,
|
||||||
|
"title", name,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_free (adaptor_icon_name);
|
||||||
|
|
||||||
|
return adaptor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* glade_widget_adaptor_from_catalog:
|
* glade_widget_adaptor_from_catalog:
|
||||||
* @catalog: A #GladeCatalog
|
* @catalog: A #GladeCatalog
|
||||||
|
@ -185,8 +185,8 @@ typedef enum
|
|||||||
* Returns: A newly created #GladeWidget for the said adaptor.
|
* Returns: A newly created #GladeWidget for the said adaptor.
|
||||||
*/
|
*/
|
||||||
typedef GladeWidget * (* GladeCreateWidgetFunc) (GladeWidgetAdaptor *adaptor,
|
typedef GladeWidget * (* GladeCreateWidgetFunc) (GladeWidgetAdaptor *adaptor,
|
||||||
const gchar *first_property_name,
|
const gchar *first_property_name,
|
||||||
va_list var_args);
|
va_list var_args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GladeSetPropertyFunc:
|
* GladeSetPropertyFunc:
|
||||||
@ -201,9 +201,9 @@ typedef GladeWidget * (* GladeCreateWidgetFunc) (GladeWidgetAdaptor *adaptor,
|
|||||||
* Sets @value on @object for a given #GladePropertyClass
|
* Sets @value on @object for a given #GladePropertyClass
|
||||||
*/
|
*/
|
||||||
typedef void (* GladeSetPropertyFunc) (GladeWidgetAdaptor *adaptor,
|
typedef void (* GladeSetPropertyFunc) (GladeWidgetAdaptor *adaptor,
|
||||||
GObject *object,
|
GObject *object,
|
||||||
const gchar *property_name,
|
const gchar *property_name,
|
||||||
const GValue *value);
|
const GValue *value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GladeGetPropertyFunc:
|
* GladeGetPropertyFunc:
|
||||||
@ -215,7 +215,7 @@ typedef void (* GladeSetPropertyFunc) (GladeWidgetAdaptor *adaptor,
|
|||||||
* Gets @value on @object for a given #GladePropertyClass
|
* Gets @value on @object for a given #GladePropertyClass
|
||||||
*/
|
*/
|
||||||
typedef void (* GladeGetPropertyFunc) (GladeWidgetAdaptor *adaptor,
|
typedef void (* GladeGetPropertyFunc) (GladeWidgetAdaptor *adaptor,
|
||||||
GObject *object,
|
GObject *object,
|
||||||
const gchar *property_name,
|
const gchar *property_name,
|
||||||
GValue *value);
|
GValue *value);
|
||||||
|
|
||||||
@ -686,12 +686,18 @@ G_CONST_RETURN gchar *glade_widget_adaptor_get_missing_icon (GladeWidgetAdaptor
|
|||||||
G_CONST_RETURN GList *glade_widget_adaptor_get_properties (GladeWidgetAdaptor *adaptor);
|
G_CONST_RETURN GList *glade_widget_adaptor_get_properties (GladeWidgetAdaptor *adaptor);
|
||||||
G_CONST_RETURN GList *glade_widget_adaptor_get_packing_props(GladeWidgetAdaptor *adaptor);
|
G_CONST_RETURN GList *glade_widget_adaptor_get_packing_props(GladeWidgetAdaptor *adaptor);
|
||||||
G_CONST_RETURN GList *glade_widget_adaptor_get_signals (GladeWidgetAdaptor *adaptor);
|
G_CONST_RETURN GList *glade_widget_adaptor_get_signals (GladeWidgetAdaptor *adaptor);
|
||||||
|
G_CONST_RETURN gchar *glade_widget_adaptor_get_template (GladeWidgetAdaptor *adaptor);
|
||||||
|
|
||||||
GList *glade_widget_adaptor_list_adaptors (void);
|
GList *glade_widget_adaptor_list_adaptors (void);
|
||||||
|
|
||||||
GladeWidgetAdaptor *glade_widget_adaptor_from_catalog (GladeCatalog *catalog,
|
GladeWidgetAdaptor *glade_widget_adaptor_from_catalog (GladeCatalog *catalog,
|
||||||
GladeXmlNode *class_node,
|
GladeXmlNode *class_node,
|
||||||
GModule *module);
|
GModule *module);
|
||||||
|
|
||||||
|
GladeWidgetAdaptor *glade_widget_adaptor_from_composite_template (GType template_type,
|
||||||
|
const gchar *template_xml,
|
||||||
|
const gchar *generic_name,
|
||||||
|
const gchar *icon_name);
|
||||||
|
|
||||||
void glade_widget_adaptor_register (GladeWidgetAdaptor *adaptor);
|
void glade_widget_adaptor_register (GladeWidgetAdaptor *adaptor);
|
||||||
|
|
||||||
|
@ -46,5 +46,6 @@
|
|||||||
#include <gladeui/glade-displayable-values.h>
|
#include <gladeui/glade-displayable-values.h>
|
||||||
#include <gladeui/glade-cell-renderer-icon.h>
|
#include <gladeui/glade-cell-renderer-icon.h>
|
||||||
#include <gladeui/glade-cursor.h>
|
#include <gladeui/glade-cursor.h>
|
||||||
|
#include <gladeui/glade-composite-template.h>
|
||||||
|
|
||||||
#endif /* __GLADE_H__ */
|
#endif /* __GLADE_H__ */
|
||||||
|
@ -1367,6 +1367,75 @@ glade_gtk_container_get_property (GladeWidgetAdaptor *adaptor,
|
|||||||
else GWA_GET_CLASS (G_TYPE_OBJECT)->get_property (adaptor, object, id, value);
|
else GWA_GET_CLASS (G_TYPE_OBJECT)->get_property (adaptor, object, id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glade_gtk_container_action_activate (GladeWidgetAdaptor *adaptor,
|
||||||
|
GObject *object,
|
||||||
|
const gchar *action_path)
|
||||||
|
{
|
||||||
|
GladeWidget *gwidget = glade_widget_get_from_gobject (object);
|
||||||
|
|
||||||
|
if (strcmp (action_path, "template") == 0)
|
||||||
|
{
|
||||||
|
GtkFileFilter *filter = gtk_file_filter_new ();
|
||||||
|
gchar *template_class, *template_file;
|
||||||
|
GtkWidget *dialog, *help_label;
|
||||||
|
GtkFileChooser *chooser;
|
||||||
|
|
||||||
|
gtk_file_filter_add_pattern (filter, "*.ui");
|
||||||
|
|
||||||
|
dialog = gtk_file_chooser_dialog_new (_("Save Template"),
|
||||||
|
GTK_WINDOW (glade_app_get_window ()),
|
||||||
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||||
|
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
chooser = GTK_FILE_CHOOSER (dialog);
|
||||||
|
gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
|
||||||
|
gtk_file_chooser_set_filter (chooser, filter);
|
||||||
|
help_label = gtk_label_new (_("NOTE: the base name of the file will be used"
|
||||||
|
" as the class name so it should be in CamelCase"));
|
||||||
|
gtk_file_chooser_set_extra_widget (chooser, help_label);
|
||||||
|
gtk_widget_show (help_label);
|
||||||
|
|
||||||
|
template_class = g_strconcat ("My", G_OBJECT_TYPE_NAME (object), NULL);
|
||||||
|
template_file = g_strconcat (template_class, ".ui", NULL);
|
||||||
|
|
||||||
|
gtk_file_chooser_set_current_folder (chooser, g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES));
|
||||||
|
gtk_file_chooser_set_current_name (chooser, template_file);
|
||||||
|
|
||||||
|
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||||
|
{
|
||||||
|
gchar *filename = gtk_file_chooser_get_filename (chooser);
|
||||||
|
gchar *basename = g_path_get_basename (filename);
|
||||||
|
gchar *dot = g_strrstr (basename, ".ui");
|
||||||
|
|
||||||
|
/* Strip file extension to get the class name */
|
||||||
|
if (dot)
|
||||||
|
{
|
||||||
|
*dot = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Or add it if it is not present */
|
||||||
|
gchar *tmp = g_strconcat (filename, ".ui", NULL);
|
||||||
|
g_free (filename);
|
||||||
|
filename = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
glade_composite_template_save_from_widget (gwidget, basename, filename);
|
||||||
|
|
||||||
|
g_free (basename);
|
||||||
|
g_free (filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (template_class);
|
||||||
|
g_free (template_file);
|
||||||
|
gtk_widget_destroy (dialog);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GWA_GET_CLASS (GTK_TYPE_WIDGET)->action_activate (adaptor, object, action_path);
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------- GtkBox ------------------------------ */
|
/* ----------------------------- GtkBox ------------------------------ */
|
||||||
|
|
||||||
GladeWidget *
|
GladeWidget *
|
||||||
|
@ -297,7 +297,10 @@ embedded in another object</_tooltip>
|
|||||||
<get-children-function>glade_gtk_container_get_children</get-children-function>
|
<get-children-function>glade_gtk_container_get_children</get-children-function>
|
||||||
<set-property-function>glade_gtk_container_set_property</set-property-function>
|
<set-property-function>glade_gtk_container_set_property</set-property-function>
|
||||||
<get-property-function>glade_gtk_container_get_property</get-property-function>
|
<get-property-function>glade_gtk_container_get_property</get-property-function>
|
||||||
|
<action-activate-function>glade_gtk_container_action_activate</action-activate-function>
|
||||||
|
<actions>
|
||||||
|
<action id="template" _name="Export as template" stock="gtk-convert" important="True"/>
|
||||||
|
</actions>
|
||||||
<properties>
|
<properties>
|
||||||
<property id="glade-template-class" _name="Template Class" save="False" custom-layout="True">
|
<property id="glade-template-class" _name="Template Class" save="False" custom-layout="True">
|
||||||
<parameter-spec>
|
<parameter-spec>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user