Commit a19c419e authored by Tristan Van Berkom's avatar Tristan Van Berkom

fixed memory leaks of description strings in usage of


	* gladeui/glade-command.[ch]: 
	  fixed memory leaks of description strings in usage of glade_command_push_group()
	  
	* gladeui/glade-widget.[ch]: Added convenience apis to set sensitivity on
	  GladeWidgetActions.

	* gladeui/glade-widget-adaptor.[ch], gladeui/glade-xml-utils.c: Added
	  deep_post_create() vfunc, in this one you must always chain up to the parent.

	* plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: Added "Add/Remove" parent
	  feature (bug 343786), implemented types: Alignment, Viewport, Event Box, Frame,
	  Aspect Frame, Scrolled Window, Expander, Table, Horizontal Box, Vertical Box,
	  Horizontal Panes, Vertical Panes


svn path=/trunk/; revision=1492
parent 111575fd
2006-07-18 Tristan Van Berkom <tvb@gnome.org>
* gladeui/glade-command.[ch]:
fixed memory leaks of description strings in usage of glade_command_push_group()
* gladeui/glade-widget.[ch]: Added convenience apis to set sensitivity on
GladeWidgetActions.
* gladeui/glade-widget-adaptor.[ch], gladeui/glade-xml-utils.c: Added
deep_post_create() vfunc, in this one you must always chain up to the parent.
* plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: Added "Add/Remove" parent
feature (bug 343786), implemented types: Alignment, Viewport, Event Box, Frame,
Aspect Frame, Scrolled Window, Expander, Table, Horizontal Box, Vertical Box,
Horizontal Panes, Vertical Panes
2007-07-18 Vincent Geddes <vgeddes@gnome.org>
* gladeui/glade-design-layout.h: Make header file look pretty.
......
......@@ -33,16 +33,6 @@ to initialize the Glade core.
@gladeapp: the object which received the signal.
<!-- ##### SIGNAL GladeApp::widget-event ##### -->
<para>
</para>
@gladeapp: the object which received the signal.
@arg1:
@event:
@Returns:
<!-- ##### ARG GladeApp:active-project ##### -->
<para>
......
......@@ -98,6 +98,8 @@ and undo those items; each #GladeProject has its own Undo/Redo stack.
</para>
@widgets:
@return_placeholders:
@Returns:
<!-- ##### STRUCT GCSetPropData ##### -->
......
......@@ -24,6 +24,16 @@ A widget to view the project hierarchy
GladeProjectView
<!-- ##### SIGNAL GladeApp::widget-event ##### -->
<para>
</para>
@gladeapp: the object which received the signal.
@arg1:
@event:
@Returns:
<!-- ##### USER_FUNCTION GladeEditorLaunchFunc ##### -->
<para>
......
......@@ -260,7 +260,7 @@ catalog_sort (GList *catalogs)
(catalogs, catalog->dep_catalog,
(GCompareFunc)catalog_find_by_name);
if ((cat = node->data) == NULL)
if (!node || (cat = node->data) == NULL)
{
g_critical ("Catalog %s depends on catalog %s, not found",
catalog->name, catalog->dep_catalog);
......
......@@ -989,6 +989,7 @@ glade_command_add (GList *widgets,
/**
* glade_command_remove:
* @widgets: a #GList of #GladeWidgets
* @return_placeholders: whether or not to return a list of placehodlers
*
* Performs a remove command on all widgets in @widgets from @parent.
*/
......@@ -998,6 +999,7 @@ glade_command_remove (GList *widgets)
GladeCommandAddRemove *me;
GladeWidget *widget = NULL;
CommandData *cdata;
GtkWidget *placeholder;
GList *list, *l;
g_return_if_fail (widgets != NULL);
......@@ -1012,8 +1014,8 @@ glade_command_remove (GList *widgets)
widget = list->data;
if (widget->internal)
{
glade_util_ui_message (glade_app_get_window(),
GLADE_UI_WARN,
glade_util_ui_message (glade_app_get_window(),
GLADE_UI_WARN,
_("You cannot remove a widget internal to a composite widget."));
return;
}
......@@ -1037,8 +1039,9 @@ glade_command_remove (GList *widgets)
glade_widget_placeholder_relation
(cdata->parent, cdata->widget))
{
glade_command_placeholder_connect
(cdata, GLADE_PLACEHOLDER (glade_placeholder_new ()));
placeholder = glade_placeholder_new ();
glade_command_placeholder_connect
(cdata, GLADE_PLACEHOLDER (placeholder));
}
me->widgets = g_list_prepend (me->widgets, cdata);
......@@ -1074,7 +1077,7 @@ glade_command_remove (GList *widgets)
glade_project_push_undo (GLADE_PROJECT (widget->project), GLADE_COMMAND (me));
else
g_object_unref (G_OBJECT (me));
} /* end of glade_command_remove() */
static void
......@@ -1543,7 +1546,6 @@ glade_command_create(GladeWidgetAdaptor *adaptor, GladeWidget *parent, GladePlac
{
GladeWidget *widget;
GList *widgets = NULL;
gchar *description;
g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
......@@ -1557,8 +1559,7 @@ glade_command_create(GladeWidgetAdaptor *adaptor, GladeWidget *parent, GladePlac
return NULL;
}
widgets = g_list_prepend(widgets, widget);
description = g_strdup_printf (_("Create %s"), g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_push_group(description);
glade_command_push_group(_("Create %s"), g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_add(widgets, parent, placeholder, FALSE);
glade_command_pop_group();
......@@ -1571,6 +1572,7 @@ glade_command_create(GladeWidgetAdaptor *adaptor, GladeWidget *parent, GladePlac
/**
* glade_command_delete:
* @widgets: a #GList of #GladeWidgets
* @return_placeholders: whether or not to return a list of placehodlers
*
* Performs a delete command on the list of widgets.
*/
......@@ -1578,13 +1580,12 @@ void
glade_command_delete(GList *widgets)
{
GladeWidget *widget;
gchar *description;
GList *placehodlers;
g_return_if_fail (widgets != NULL);
widget = widgets->data;
description = g_strdup_printf (_("Delete %s"), g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_push_group(description);
glade_command_push_group(_("Delete %s"), g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_remove(widgets);
glade_command_pop_group();
}
......@@ -1600,7 +1601,6 @@ glade_command_cut(GList *widgets)
{
GladeWidget *widget;
GList *l;
gchar *description;
g_return_if_fail (widgets != NULL);
......@@ -1608,8 +1608,7 @@ glade_command_cut(GList *widgets)
g_object_set_data (G_OBJECT (l->data), "glade-command-was-cut", GINT_TO_POINTER (TRUE));
widget = widgets->data;
description = g_strdup_printf (_("Cut %s"), g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_push_group(description);
glade_command_push_group(_("Cut %s"), g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_remove(widgets);
glade_command_clipboard_add(widgets);
glade_command_pop_group();
......@@ -1626,7 +1625,6 @@ glade_command_copy(GList *widgets)
{
GList *list, *copied_widgets = NULL;
GladeWidget *copied_widget = NULL;
gchar *description;
g_return_if_fail (widgets != NULL);
......@@ -1635,8 +1633,7 @@ glade_command_copy(GList *widgets)
copied_widget = glade_widget_dup(list->data, FALSE);
copied_widgets = g_list_prepend(copied_widgets, copied_widget);
}
description = g_strdup_printf (_("Copy %s"), g_list_length (widgets) == 1 ? copied_widget->name : _("multiple"));
glade_command_push_group(description);
glade_command_push_group(_("Copy %s"), g_list_length (widgets) == 1 ? copied_widget->name : _("multiple"));
glade_command_clipboard_add(copied_widgets);
glade_command_pop_group();
......@@ -1659,7 +1656,6 @@ glade_command_paste(GList *widgets, GladeWidget *parent, GladePlaceholder *place
{
GList *list, *copied_widgets = NULL;
GladeWidget *copied_widget = NULL;
gchar *description;
gboolean exact;
g_return_if_fail (widgets != NULL);
......@@ -1671,8 +1667,7 @@ glade_command_paste(GList *widgets, GladeWidget *parent, GladePlaceholder *place
copied_widget = glade_widget_dup(list->data, exact);
copied_widgets = g_list_prepend(copied_widgets, copied_widget);
}
description = g_strdup_printf (_("Paste %s"), g_list_length (widgets) == 1 ? copied_widget->name : _("multiple"));
glade_command_push_group(description);
glade_command_push_group(_("Paste %s"), g_list_length (widgets) == 1 ? copied_widget->name : _("multiple"));
glade_command_add(copied_widgets, parent, placeholder, TRUE);
glade_command_pop_group();
......@@ -1694,13 +1689,13 @@ void
glade_command_dnd(GList *widgets, GladeWidget *parent, GladePlaceholder *placeholder)
{
GladeWidget *widget;
gchar *description;
GList *placeholders;
g_return_if_fail (widgets != NULL);
widget = widgets->data;
description = g_strdup_printf (_("Drag-n-Drop from %s to %s"), parent->name, g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_push_group(description);
glade_command_push_group(_("Drag-n-Drop from %s to %s"),
parent->name, g_list_length (widgets) == 1 ? widget->name : _("multiple"));
glade_command_remove(widgets);
glade_command_add(widgets, parent, placeholder, TRUE);
glade_command_pop_group();
......
......@@ -244,6 +244,7 @@ glade_popup_action_populate_menu_real (GtkWidget *menu,
(a->actions) ? NULL : a->klass->path);
g_object_set_data (G_OBJECT (item), "gwa-data", data);
gtk_widget_set_sensitive (item, a->sensitive);
if (submenu)
......
......@@ -768,6 +768,7 @@ glade_widget_adaptor_class_init (GladeWidgetAdaptorClass *adaptor_class)
object_class->get_property = glade_widget_adaptor_real_get_property;
/* Class methods */
adaptor_class->deep_post_create = NULL;
adaptor_class->post_create = NULL;
adaptor_class->get_internal_child = NULL;
adaptor_class->verify_property = NULL;
......@@ -947,7 +948,12 @@ gwa_extend_with_node_load_sym (GladeWidgetAdaptorClass *klass,
GLADE_TAG_CONSTRUCTOR_FUNCTION,
&symbol))
object_class->constructor = symbol;
if (glade_xml_load_sym_from_node (node, module,
GLADE_TAG_DEEP_POST_CREATE_FUNCTION,
&symbol))
klass->deep_post_create = symbol;
if (glade_xml_load_sym_from_node (node, module,
GLADE_TAG_POST_CREATE_FUNCTION,
&symbol))
......@@ -1981,6 +1987,13 @@ glade_widget_adaptor_post_create (GladeWidgetAdaptor *adaptor,
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (object), adaptor->type));
/* Run post_create in 2 stages, one that chains up and all class adaptors
* in the hierarchy get a peek, another that is used to setup placeholders
* and things that differ from the child/parent implementations
*/
if (GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->deep_post_create)
GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->deep_post_create (adaptor, object, reason);
if (GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->post_create)
GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->post_create (adaptor, object, reason);
/* XXX Dont complain here if no implementation is found */
......
......@@ -411,9 +411,17 @@ struct _GladeWidgetAdaptorClass
gint default_width; /* Default width in GladeDesignLayout */
gint default_height; /* Default height in GladeDesignLayout */
GladePostCreateFunc deep_post_create; /* Executed after widget creation:
* plugins use this to setup various
* support codes (adaptors must always
* chain up in this stage of instantiation).
*/
GladePostCreateFunc post_create; /* Executed after widget creation:
* plugins use this to setup various
* support codes.
* support codes (adaptors are free here
* to chain up or not in this stage of
* instantiation).
*/
GladeGetInternalFunc get_internal_child; /* Retrieves the the internal child
......
......@@ -3890,6 +3890,63 @@ glade_widget_get_pack_action (GladeWidget *widget, const gchar *action_path)
return glade_widget_action_lookup (&widget->packing_actions, action_path, FALSE);
}
/**
* glade_widget_set_action_sensitive:
* @widget: a #GladeWidget
* @action_path: a full action path including groups
* @sensitive: setting sensitive or insensitive
*
* Sets the sensitivity of @action_path in @widget
*
* Returns: whether @action_path was found or not.
*/
gboolean
glade_widget_set_action_sensitive (GladeWidget *widget,
const gchar *action_path,
gboolean sensitive)
{
GladeWidgetAction *action;
g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
if ((action = glade_widget_get_action (widget, action_path)) != NULL)
{
glade_widget_action_set_sensitive (action, sensitive);
return TRUE;
}
return FALSE;
}
/**
* glade_widget_set_pack_action_sensitive:
* @widget: a #GladeWidget
* @action_path: a full action path including groups
* @sensitive: setting sensitive or insensitive
*
* Sets the sensitivity of @action_path in @widget
*
* Returns: whether @action_path was found or not.
*/
gboolean
glade_widget_set_pack_action_sensitive (GladeWidget *widget,
const gchar *action_path,
gboolean sensitive)
{
GladeWidgetAction *action;
g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
if ((action = glade_widget_get_pack_action (widget, action_path)) != NULL)
{
glade_widget_action_set_sensitive (action, sensitive);
return TRUE;
}
return FALSE;
}
/**
* glade_widget_remove_action:
* @widget: a #GladeWidget
......
......@@ -196,12 +196,20 @@ gboolean glade_widget_event (GladeWidget *g
gboolean glade_widget_placeholder_relation (GladeWidget *parent,
GladeWidget *widget);
GladeWidgetAction * glade_widget_get_action (GladeWidget *widget,
GladeWidgetAction *glade_widget_get_action (GladeWidget *widget,
const gchar *action_path);
GladeWidgetAction * glade_widget_get_pack_action (GladeWidget *widget,
GladeWidgetAction *glade_widget_get_pack_action (GladeWidget *widget,
const gchar *action_path);
gboolean glade_widget_set_action_sensitive (GladeWidget *widget,
const gchar *action_path,
gboolean sensitive);
gboolean glade_widget_set_pack_action_sensitive (GladeWidget *widget,
const gchar *action_path,
gboolean sensitive);
void glade_widget_remove_action (GladeWidget *widget,
const gchar *action_path);
......
......@@ -46,6 +46,7 @@ typedef struct _GladeXmlDoc GladeXmlDoc;
#define GLADE_TAG_DISABLED "disabled"
#define GLADE_TAG_DEFAULT_PALETTE_STATE "default-palette-state"
#define GLADE_TAG_REPLACE_CHILD_FUNCTION "replace-child-function"
#define GLADE_TAG_DEEP_POST_CREATE_FUNCTION "deep-post-create-function"
#define GLADE_TAG_POST_CREATE_FUNCTION "post-create-function"
#define GLADE_TAG_GET_INTERNAL_CHILD_FUNCTION "get-internal-child-function"
#define GLADE_TAG_ADD_CHILD_FUNCTION "add-child-function"
......
......@@ -242,6 +242,38 @@ glade_gtk_stop_emission_POINTER (gpointer instance, gpointer dummy, gpointer dat
}
/* ----------------------------- GtkWidget ------------------------------ */
static void
widget_parent_changed (GtkWidget *widget,
GParamSpec *pspec,
GladeWidgetAdaptor *adaptor)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (widget);
if (gwidget->parent && !GTK_IS_WINDOW (glade_widget_get_object (gwidget->parent)))
glade_widget_set_action_sensitive (gwidget, "remove_parent", TRUE);
else
glade_widget_set_action_sensitive (gwidget, "remove_parent", FALSE);
}
void
glade_gtk_widget_deep_post_create (GladeWidgetAdaptor *adaptor,
GObject *widget,
GladeCreateReason reason)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (widget);
glade_widget_set_action_sensitive (gwidget, "remove_parent", FALSE);
if (GTK_IS_WINDOW (widget))
glade_widget_set_action_sensitive (gwidget, "add_parent", FALSE);
/* Watch parents and set actions sensitive/insensitive */
g_signal_connect (G_OBJECT (widget), "notify::parent",
G_CALLBACK (widget_parent_changed), adaptor);
}
void
glade_gtk_widget_set_property (GladeWidgetAdaptor *adaptor,
GObject *object,
......@@ -284,6 +316,154 @@ glade_gtk_widget_get_property (GladeWidgetAdaptor *adaptor,
GWA_GET_CLASS (G_TYPE_OBJECT)->get_property (adaptor, object, id, value);
}
static GList *
create_command_property_list (GladeWidget *gnew, GList *saved_props)
{
GList *l, *command_properties = NULL;
for (l = saved_props; l; l = l->next)
{
GladeProperty *property = l->data;
GladeProperty *orig_prop = glade_widget_get_pack_property (gnew, property->klass->id);
GCSetPropData *pdata = g_new0 (GCSetPropData, 1);
pdata->property = orig_prop;
pdata->old_value = g_new0 (GValue, 1);
pdata->new_value = g_new0 (GValue, 1);
glade_property_get_value (orig_prop, pdata->old_value);
glade_property_get_value (property, pdata->new_value);
command_properties = g_list_prepend (command_properties, pdata);
}
return g_list_reverse (command_properties);
}
void
glade_gtk_widget_action_activate (GladeWidgetAdaptor *adaptor,
GObject *object,
const gchar *action_path)
{
GladeWidget *gwidget = glade_widget_get_from_gobject (object), *gparent;
GList this_widget = { 0, }, that_widget = { 0, };
GtkWidget *parent = GTK_WIDGET (object)->parent;
g_assert (parent);
gparent = glade_widget_get_from_gobject (parent);
if (strcmp (action_path, "remove_parent") == 0)
{
GladeWidget *new_gparent = gparent->parent;
/* Since toplevel project objects for now must be GtkWindow,
* we'll just assert this for now (should be an insensitive action).
*/
g_assert (!GTK_IS_WINDOW (parent));
glade_command_push_group (_("Removing parent of %s"),
gwidget->name);
/* Remove "this" widget */
this_widget.data = gwidget;
glade_command_delete (&this_widget);
/* Delete the parent */
that_widget.data = gparent;
glade_command_delete (&that_widget);
/* Add "this" widget to the new parent */
glade_command_paste(&this_widget, new_gparent, NULL);
glade_command_pop_group ();
}
else if (strncmp (action_path, "add_parent/", 11) == 0)
{
GType new_type = 0;
if (strcmp (action_path + 11, "alignment") == 0)
new_type = GTK_TYPE_ALIGNMENT;
else if (strcmp (action_path + 11, "viewport") == 0)
new_type = GTK_TYPE_VIEWPORT;
else if (strcmp (action_path + 11, "eventbox") == 0)
new_type = GTK_TYPE_EVENT_BOX;
else if (strcmp (action_path + 11, "frame") == 0)
new_type = GTK_TYPE_FRAME;
else if (strcmp (action_path + 11, "aspect_frame") == 0)
new_type = GTK_TYPE_ASPECT_FRAME;
else if (strcmp (action_path + 11, "scrolled_window") == 0)
new_type = GTK_TYPE_SCROLLED_WINDOW;
else if (strcmp (action_path + 11, "expander") == 0)
new_type = GTK_TYPE_EXPANDER;
else if (strcmp (action_path + 11, "table") == 0)
new_type = GTK_TYPE_TABLE;
else if (strcmp (action_path + 11, "hbox") == 0)
new_type = GTK_TYPE_HBOX;
else if (strcmp (action_path + 11, "vbox") == 0)
new_type = GTK_TYPE_VBOX;
else if (strcmp (action_path + 11, "hpaned") == 0)
new_type = GTK_TYPE_HPANED;
else if (strcmp (action_path + 11, "vpaned") == 0)
new_type = GTK_TYPE_VPANED;
if (new_type)
{
GladeWidgetAdaptor *adaptor = glade_widget_adaptor_get_by_type (new_type);
GList *saved_props, *prop_cmds;
glade_command_push_group (_("Adding parent %s to %s"),
adaptor->title, gwidget->name);
/* Record packing properties */
saved_props = glade_widget_dup_properties (gwidget->packing_properties, FALSE);
/* Remove "this" widget */
this_widget.data = gwidget;
glade_command_delete (&this_widget);
/* Create new widget and put it where the placeholder was */
that_widget.data =
glade_command_create (adaptor, gparent, NULL,
glade_widget_get_project (gparent));
/* Remove the alignment that we added in the frame's post_create... */
if (new_type == GTK_TYPE_FRAME)
{
GObject *frame = glade_widget_get_object (that_widget.data);
GladeWidget *galign = glade_widget_get_from_gobject (GTK_BIN (frame)->child);
GList to_delete = { 0, };
to_delete.data = galign;
glade_command_delete (&to_delete);
}
/* Create heavy-duty glade-command properties stuff */
prop_cmds = create_command_property_list (that_widget.data, saved_props);
g_list_foreach (saved_props, (GFunc)g_object_unref, NULL);
g_list_free (saved_props);
/* Apply the properties in an undoable way */
if (prop_cmds)
glade_command_set_properties_list (glade_widget_get_project (gparent), prop_cmds);
/* Add "this" widget to the new parent */
glade_command_paste(&this_widget, GLADE_WIDGET (that_widget.data), NULL);
glade_command_pop_group ();
}
}
else
GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor,
object,
action_path);
}
/* ----------------------------- GtkContainer ------------------------------ */
void
glade_gtk_container_post_create (GladeWidgetAdaptor *adaptor,
......
......@@ -7,8 +7,29 @@
<glade-widget-class name="GtkWidget" _title="Widget" default-width="100" default-height="60">
<deep-post-create-function>glade_gtk_widget_deep_post_create</deep-post-create-function>
<set-property-function>glade_gtk_widget_set_property</set-property-function>
<get-property-function>glade_gtk_widget_get_property</get-property-function>
<action-activate-function>glade_gtk_widget_action_activate</action-activate-function>
<actions>
<action id="remove_parent" _name="Remove Parent" stock="gtk-remove"/>
<action id="add_parent" _name="Add Parent" stock="gtk-add">
<action id="alignment" _name="Alignment"/>
<action id="viewport" _name="Viewport"/>
<action id="eventbox" _name="Event Box"/>
<action id="frame" _name="Frame"/>
<action id="aspect_frame" _name="Aspect Frame"/>
<action id="scrolled_window" _name="Scrolled Window"/>
<action id="expander" _name="Expander"/>
<action id="table" _name="Table"/>
<action id="hbox" _name="Horizontal Box"/>
<action id="vbox" _name="Vertical Box"/>
<action id="hpaned" _name="Horizontal Panes"/>
<action id="vpaned" _name="Vertical Panes"/>
</action>
</actions>
<properties>
<property id="visible" default="True" common="True" ignore="True"/>
......
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