Commit 2c8f3b86 authored by Tristan Van Berkom's avatar Tristan Van Berkom
Browse files

* gladeui/glade-command.[ch], Added GladeProject member to base command structure, now

	  all commands reffer to that structure instead of trying to pull a project pointer from
	  a widget.

	* gladeui/glade-project.c: Unset project pointer on widgets when they leave the project,
	  manage an "in_project" flag on widgets to differenciate the moment when they widgets are
	  loading and have the project pointer but are still not added to the project yet. Also speed up
	  glade_project_has_object() by not traversing the list but simply checking the widget's project
	  and in_project flag.

	* gladeui/glade-widget.[ch]: Added the "in_project" flag to GladeWidget, fixed glade_widget_rebuild
	  to save the previous project pointer.
parent 093d6de3
2011-01-01 Tristan Van Berkom <tristanvb@openismus.com>
* gladeui/glade-command.[ch], Added GladeProject member to base command structure, now
all commands reffer to that structure instead of trying to pull a project pointer from
a widget.
* gladeui/glade-project.c: Unset project pointer on widgets when they leave the project,
manage an "in_project" flag on widgets to differenciate the moment when they widgets are
loading and have the project pointer but are still not added to the project yet. Also speed up
glade_project_has_object() by not traversing the list but simply checking the widget's project
and in_project flag.
* gladeui/glade-widget.[ch]: Added the "in_project" flag to GladeWidget, fixed glade_widget_rebuild
to save the previous project pointer.
2010-12-31 Tristan Van Berkom <tristanvb@openismus.com>
* gladeui/glade-project.c: Further fixing project dispose cycle, still leaking a little
......
......@@ -60,7 +60,6 @@ typedef struct
{
GladeWidget *widget;
GladeWidget *parent;
GladeProject *project;
GList *reffed;
GladePlaceholder *placeholder;
gboolean props_recorded;
......@@ -628,6 +627,7 @@ glade_command_set_properties_list (GladeProject * project, GList * props)
me = (GladeCommandSetProperty *)
g_object_new (GLADE_COMMAND_SET_PROPERTY_TYPE, NULL);
cmd = GLADE_COMMAND (me);
cmd->project = project;
/* Ref all props */
for (list = props; list; list = list->next)
......@@ -639,21 +639,18 @@ glade_command_set_properties_list (GladeProject * project, GList * props)
me->sdata = props;
cmd->description = glade_command_set_property_description (me);
multiple = g_list_length (me->sdata) > 1;
if (multiple)
glade_command_push_group (cmd->description);
glade_command_check_group (GLADE_COMMAND (me));
/* Push onto undo stack only if it executes successfully. */
success = glade_command_set_property_execute (GLADE_COMMAND (me));
success = glade_command_set_property_execute (cmd);
if (success)
glade_project_push_undo (GLADE_PROJECT (project), GLADE_COMMAND (me));
glade_project_push_undo (cmd->project, cmd);
else
/* No leaks on my shift! */
g_object_unref (G_OBJECT (me));
if (multiple)
......@@ -782,7 +779,7 @@ glade_command_set_name_execute (GladeCommand * cmd)
g_return_val_if_fail (me->widget != NULL, TRUE);
g_return_val_if_fail (me->name != NULL, TRUE);
glade_project_set_widget_name (me->widget->project, me->widget, me->name);
glade_project_set_widget_name (cmd->project, me->widget, me->name);
tmp = me->old_name;
me->old_name = me->name;
......@@ -863,6 +860,7 @@ glade_command_set_name (GladeWidget * widget, const gchar * name)
me = g_object_new (GLADE_COMMAND_SET_NAME_TYPE, NULL);
cmd = GLADE_COMMAND (me);
cmd->project = widget->project;
me->widget = widget;
me->name = g_strdup (name);
......@@ -874,8 +872,7 @@ glade_command_set_name (GladeWidget * widget, const gchar * name)
glade_command_check_group (GLADE_COMMAND (me));
if (glade_command_set_name_execute (GLADE_COMMAND (me)))
glade_project_push_undo (GLADE_PROJECT (widget->project),
GLADE_COMMAND (me));
glade_project_push_undo (cmd->project, cmd);
else
g_object_unref (G_OBJECT (me));
}
......@@ -891,7 +888,6 @@ glade_command_set_name (GladeWidget * widget, const gchar * name)
typedef struct
{
GladeCommand parent;
GladeProject *project;
GList *widgets;
gboolean add;
gboolean from_clipboard;
......@@ -976,6 +972,7 @@ glade_command_add (GList * widgets,
GladePlaceholder * placeholder, gboolean pasting)
{
GladeCommandAddRemove *me;
GladeCommand *cmd;
CommandData *cdata;
GladeWidget *widget = NULL;
GList *l, *list, *children, *placeholders = NULL;
......@@ -985,6 +982,7 @@ glade_command_add (GList * widgets,
g_return_if_fail (parent == NULL || GLADE_IS_WIDGET (parent));
me = g_object_new (GLADE_COMMAND_ADD_REMOVE_TYPE, NULL);
cmd = GLADE_COMMAND (me);
me->add = TRUE;
me->from_clipboard = pasting;
......@@ -994,9 +992,9 @@ glade_command_add (GList * widgets,
*/
widget = GLADE_WIDGET (widgets->data);
if (placeholder && GWA_IS_TOPLEVEL (widget->adaptor) == FALSE)
me->project = glade_placeholder_get_project (placeholder);
cmd->project = glade_placeholder_get_project (placeholder);
else
me->project = glade_app_get_project ();
cmd->project = glade_app_get_project ();
GLADE_COMMAND (me)->description =
g_strdup_printf (_("Add %s"), g_list_length (widgets) == 1 ?
......@@ -1063,13 +1061,6 @@ glade_command_add (GList * widgets,
}
}
/*
* Save a copy of the original project so we can forward that to glade-project,
* who'll copy in any resource files needed by any properties that are getting
* cross-project pasted.
*/
cdata->project = cdata->widget->project;
me->widgets = g_list_prepend (me->widgets, cdata);
}
......@@ -1078,17 +1069,15 @@ glade_command_add (GList * widgets,
/*
* Push it onto the undo stack only on success
*/
if (glade_command_add_remove_execute (GLADE_COMMAND (me)))
glade_project_push_undo (glade_app_get_project (), GLADE_COMMAND (me));
if (glade_command_add_remove_execute (cmd))
glade_project_push_undo (cmd->project, cmd);
else
g_object_unref (G_OBJECT (me));
if (placeholders)
g_list_free (placeholders);
} /* end of glade_command_add() */
}
static void
glade_command_delete_prop_refs (GladeWidget * widget)
......@@ -1172,7 +1161,7 @@ glade_command_remove (GList * widgets)
}
}
me->project = glade_widget_get_project (widget);
GLADE_COMMAND (me)->project = glade_widget_get_project (widget);
GLADE_COMMAND (me)->description = g_strdup ("dummy");
if (g_list_length (widgets) == 1)
......@@ -1188,7 +1177,6 @@ glade_command_remove (GList * widgets)
cdata = g_new0 (CommandData, 1);
cdata->widget = g_object_ref (G_OBJECT (widget));
cdata->parent = glade_widget_get_parent (widget);
cdata->project = glade_widget_get_project (widget);
if ((cdata->reffed =
get_all_parentless_reffed_widgets (cdata->reffed, widget)) != NULL)
......@@ -1236,7 +1224,7 @@ glade_command_remove (GList * widgets)
glade_command_check_group (GLADE_COMMAND (me));
if (glade_command_add_remove_execute (GLADE_COMMAND (me)))
glade_project_push_undo (GLADE_PROJECT (widget->project),
glade_project_push_undo (GLADE_COMMAND (me)->project,
GLADE_COMMAND (me));
else
g_object_unref (G_OBJECT (me));
......@@ -1264,7 +1252,6 @@ glade_command_transfer_props (GladeWidget * gnew, GList * saved_props)
static gboolean
glade_command_add_execute (GladeCommandAddRemove * me)
{
GladeProject *active_project = glade_app_get_project (), *add_project;
CommandData *cdata;
GList *list, *l, *saved_props;
gchar *special_child_type;
......@@ -1350,6 +1337,7 @@ glade_command_add_execute (GladeCommandAddRemove * me)
glade_property_get_value (saved_prop, &value);
glade_property_set_value (widget_prop, &value);
glade_property_sync (widget_prop);
g_value_unset (&value);
}
......@@ -1384,17 +1372,12 @@ glade_command_add_execute (GladeCommandAddRemove * me)
}
}
/* Toplevels get pasted to the active project */
add_project = (me->from_clipboard && cdata->widget->parent == NULL) ?
active_project : me->project;
glade_project_add_object (add_project, cdata->project,
cdata->widget->object);
glade_project_add_object (GLADE_COMMAND (me)->project, NULL, cdata->widget->object);
for (l = cdata->reffed; l; l = l->next)
{
GladeWidget *reffed = l->data;
glade_project_add_object (add_project, cdata->project,
glade_project_add_object (GLADE_COMMAND (me)->project, NULL,
reffed->object);
}
......@@ -1405,7 +1388,6 @@ glade_command_add_execute (GladeCommandAddRemove * me)
glade_app_queue_selection_changed ();
}
return TRUE;
} /* end of glade_command_add_execute() */
static gboolean
......@@ -1419,13 +1401,15 @@ glade_command_remove_execute (GladeCommandAddRemove * me)
{
cdata = list->data;
glade_project_remove_object (GLADE_PROJECT (cdata->widget->project),
glade_widget_hide (cdata->widget);
glade_project_remove_object (GLADE_COMMAND (me)->project,
cdata->widget->object);
for (l = cdata->reffed; l; l = l->next)
{
reffed = l->data;
glade_project_remove_object (GLADE_PROJECT (cdata->widget->project),
glade_project_remove_object (GLADE_COMMAND (me)->project,
reffed->object);
}
......@@ -1437,8 +1421,6 @@ glade_command_remove_execute (GladeCommandAddRemove * me)
else
glade_widget_remove_child (cdata->parent, cdata->widget);
}
glade_widget_hide (cdata->widget);
}
return TRUE;
......@@ -1601,23 +1583,6 @@ glade_command_clipboard_add (GList * widgets)
glade_command_clipboard_add_remove_common (widgets, TRUE);
}
/**
* glade_command_clipboard_remove:
* @widgets: a #GList
*
* Performs a remove command on all widgets in @widgets from the clipboard.
*/
/* not used anywhere */
#if 0
static void
glade_command_clipboard_remove (GList * widgets)
{
glade_command_clipboard_add_remove_common (widgets, FALSE);
}
#endif
static gboolean
glade_command_clipboard_add_execute (GladeCommandClipboardAddRemove * me)
{
......@@ -1910,18 +1875,10 @@ glade_command_paste (GList * widgets, GladeWidget * parent,
{
GList *list, *copied_widgets = NULL;
GladeWidget *copied_widget = NULL;
/* GladeProject *target_project; */
gboolean exact;
g_return_if_fail (widgets != NULL);
/* if (placeholder && GWA_IS_TOPLEVEL (widget->adaptor) == FALSE) */
/* target_project = glade_placeholder_get_project (placeholder); */
/* else if (parent && GWA_IS_TOPLEVEL (widget->adaptor) == FALSE) */
/* target_project = glade_widget_get_project (parent); */
/* else */
/* target_project = glade_app_get_project(); */
for (list = widgets; list && list->data; list = list->next)
{
exact =
......@@ -1936,11 +1893,6 @@ glade_command_paste (GList * widgets, GladeWidget * parent,
g_list_length (widgets) ==
1 ? copied_widget->name : _("multiple"));
/* When pasting widgets across projects, we nullify the property references that
* are not satisfied by the paste list.
*/
glade_command_add (copied_widgets, parent, placeholder, TRUE);
glade_command_pop_group ();
......@@ -2092,6 +2044,7 @@ glade_command_add_remove_change_signal (GladeWidget * glade_widget,
me->signal = glade_signal_clone (signal);
me->new_signal = new_signal ? glade_signal_clone (new_signal) : NULL;
cmd->project = glade_widget_get_project (glade_widget);
cmd->description =
g_strdup_printf (type == GLADE_ADD ? _("Add signal handler %s") :
type == GLADE_REMOVE ? _("Remove signal handler %s") :
......@@ -2100,7 +2053,7 @@ glade_command_add_remove_change_signal (GladeWidget * glade_widget,
glade_command_check_group (GLADE_COMMAND (me));
if (glade_command_add_signal_execute (cmd))
glade_project_push_undo (GLADE_PROJECT (glade_widget->project), cmd);
glade_project_push_undo (cmd->project, cmd);
else
g_object_unref (G_OBJECT (me));
}
......@@ -2310,6 +2263,8 @@ glade_command_set_i18n (GladeProperty * property,
me->old_translatable = property->i18n_translatable;
me->old_context = g_strdup (property->i18n_context);
me->old_comment = g_strdup (property->i18n_comment);
GLADE_COMMAND (me)->project = property->widget->project;
GLADE_COMMAND (me)->description =
g_strdup_printf (_("Setting i18n metadata"));;
......@@ -2318,7 +2273,7 @@ glade_command_set_i18n (GladeProperty * property,
/* execute the command and push it on the stack if successful */
if (glade_command_set_i18n_execute (GLADE_COMMAND (me)))
{
glade_project_push_undo (glade_app_get_project (), GLADE_COMMAND (me));
glade_project_push_undo (GLADE_COMMAND (me)->project, GLADE_COMMAND (me));
}
else
{
......@@ -2338,7 +2293,6 @@ glade_command_set_i18n (GladeProperty * property,
typedef struct
{
GladeCommand parent;
GladeProject *project;
GladeNamingPolicy policy;
GladeNamingPolicy old_policy;
} GladeCommandSetPolicy;
......@@ -2357,12 +2311,8 @@ glade_command_set_policy_execute (GladeCommand * cmd)
GladeCommandSetPolicy *me = (GladeCommandSetPolicy *) cmd;
GladeNamingPolicy policy;
/* sanity check */
g_return_val_if_fail (me != NULL, TRUE);
g_return_val_if_fail (me->project != NULL, TRUE);
/* set the new policy */
glade_project_set_naming_policy (me->project, me->policy);
glade_project_set_naming_policy (cmd->project, me->policy);
/* swap the current values with the old values to prepare for undo */
policy = me->policy;
......@@ -2440,10 +2390,10 @@ glade_command_set_project_naming_policy (GladeProject * project,
/* load up the command */
me = g_object_new (GLADE_COMMAND_SET_POLICY_TYPE, NULL);
me->project = project;
me->policy = policy;
me->old_policy = glade_project_get_naming_policy (project);
GLADE_COMMAND (me)->project = project;
GLADE_COMMAND (me)->description = g_strdup_printf ("dummy string");
glade_command_check_group (GLADE_COMMAND (me));
......@@ -2453,8 +2403,7 @@ glade_command_set_project_naming_policy (GladeProject * project,
*/
if (glade_command_set_policy_execute (GLADE_COMMAND (me)))
{
glade_project_push_undo (glade_app_get_project (),
GLADE_COMMAND (me));
glade_project_push_undo (project, GLADE_COMMAND (me));
}
else
{
......@@ -2463,12 +2412,12 @@ glade_command_set_project_naming_policy (GladeProject * project,
glade_command_pop_group ();
/* XXX Do we need this ??? */
glade_editor_refresh (glade_app_get_editor ());
}
}
/******************************************************************************
*
* This command sets protection warnings on widgets
......@@ -2573,6 +2522,7 @@ glade_command_lock_widget (GladeWidget * widget, GladeWidget * locked)
me->locked = g_object_ref (locked);
me->locking = TRUE;
GLADE_COMMAND (me)->project = glade_widget_get_project (widget);
GLADE_COMMAND (me)->description =
g_strdup_printf (_("Locking %s by widget %s"), locked->name,
widget->name);
......@@ -2583,7 +2533,7 @@ glade_command_lock_widget (GladeWidget * widget, GladeWidget * locked)
* this sets the actual policy
*/
if (glade_command_lock_execute (GLADE_COMMAND (me)))
glade_project_push_undo (glade_app_get_project (), GLADE_COMMAND (me));
glade_project_push_undo (GLADE_COMMAND (me)->project, GLADE_COMMAND (me));
else
g_object_unref (G_OBJECT (me));
......@@ -2612,6 +2562,7 @@ glade_command_unlock_widget (GladeWidget * widget)
me->locked = g_object_ref (widget);
me->locking = FALSE;
GLADE_COMMAND (me)->project = glade_widget_get_project (widget);
GLADE_COMMAND (me)->description =
g_strdup_printf (_("Unlocking %s"), widget->name);
......@@ -2621,7 +2572,7 @@ glade_command_unlock_widget (GladeWidget * widget)
* this sets the actual policy
*/
if (glade_command_lock_execute (GLADE_COMMAND (me)))
glade_project_push_undo (glade_app_get_project (), GLADE_COMMAND (me));
glade_project_push_undo (GLADE_COMMAND (me)->project, GLADE_COMMAND (me));
else
g_object_unref (G_OBJECT (me));
......
......@@ -33,33 +33,35 @@ typedef struct _GCSetPropData GCSetPropData;
* their old and new #GValue.
*/
struct _GCSetPropData {
GladeProperty *property;
GValue *new_value;
GValue *old_value;
GladeProperty *property;
GValue *new_value;
GValue *old_value;
};
struct _GladeCommand
{
GObject parent;
GObject parent;
gchar *description; /* a string describing the command.
* It's used in the undo/redo menu entry.
*/
GladeProject *project; /* The project this command is created for */
gint group_id; /* If this is part of a command group, this is
* the group id (id is needed only to ensure that
* consecutive groups dont get merged).
*/
gchar *description; /* a string describing the command.
* It's used in the undo/redo menu entry.
*/
gint group_id; /* If this is part of a command group, this is
* the group id (id is needed only to ensure that
* consecutive groups dont get merged).
*/
};
struct _GladeCommandClass
{
GObjectClass parent_class;
GObjectClass parent_class;
gboolean (* execute) (GladeCommand *this_cmd);
gboolean (* undo) (GladeCommand *this_cmd);
gboolean (* unifies) (GladeCommand *this_cmd, GladeCommand *other_cmd);
void (* collapse) (GladeCommand *this_cmd, GladeCommand *other_cmd);
gboolean (* execute) (GladeCommand *this_cmd);
gboolean (* undo) (GladeCommand *this_cmd);
gboolean (* unifies) (GladeCommand *this_cmd, GladeCommand *other_cmd);
void (* collapse) (GladeCommand *this_cmd, GladeCommand *other_cmd);
};
......
......@@ -2213,7 +2213,14 @@ glade_project_verify_signals (GladeWidget * widget,
void
glade_project_verify_properties (GladeWidget * widget)
{
GladeProject *project;
g_return_if_fail (GLADE_IS_WIDGET (widget));
project = glade_widget_get_project (widget);
if (!project || project->priv->loading)
return;
glade_project_verify_properties_internal (widget, NULL, NULL, TRUE);
glade_project_verify_signals (widget, NULL, NULL, TRUE);
......@@ -2615,7 +2622,6 @@ glade_project_available_widget_name (GladeProject * project,
g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
g_return_val_if_fail (widget->project == project, FALSE);
if (!name || !name[0])
return FALSE;
......@@ -2693,7 +2699,6 @@ glade_project_new_widget_name (GladeProject * project,
g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
g_return_val_if_fail (widget->project == project, NULL);
g_return_val_if_fail (base_name && base_name[0], NULL);
context = name_context_by_widget (project, widget);
......@@ -2740,7 +2745,6 @@ glade_project_set_widget_name (GladeProject * project,
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (GLADE_IS_WIDGET (widget));
g_return_if_fail (widget->project == project);
g_return_if_fail (name && name[0]);
if (strcmp (name, widget->name) == 0)
......@@ -2798,6 +2802,14 @@ glade_project_update_previewable (GladeProject * project)
g_object_notify (G_OBJECT (project), "previewable");
}
static void
glade_project_notify_row_has_child (GladeProject *project,
GladeWidget *gwidget,
gboolean adding)
{
}
static void
glade_project_notify_row_inserted (GladeProject * project,
GladeWidget * gwidget)
......@@ -2814,9 +2826,7 @@ glade_project_notify_row_inserted (GladeProject * project,
gtk_tree_model_row_inserted (GTK_TREE_MODEL (project), path, &iter);
gtk_tree_path_free (path);
/* XXX Need to check and call this
* gtk_tree_model_row_has_child_toggled
*/
glade_project_notify_row_has_child (project, gwidget, TRUE);
}
static void
......@@ -2830,10 +2840,7 @@ glade_project_notify_row_deleted (GladeProject * project, GladeWidget * gwidget)
gtk_tree_model_row_deleted (GTK_TREE_MODEL (project), path);
gtk_tree_path_free (path);
/* XXX Need to check and call this
* gtk_tree_model_row_has_child_toggled
*/
glade_project_notify_row_has_child (project, gwidget, FALSE);
project->priv->stamp++;
}
......@@ -2901,6 +2908,7 @@ glade_project_add_object (GladeProject * project,
glade_project_reserve_widget_name (project, gwidget, gwidget->name);
glade_widget_set_project (gwidget, (gpointer) project);
gwidget->in_project = TRUE;
g_object_ref_sink (gwidget);
/* Be sure to update the lists before emitting signals */
......@@ -2941,9 +2949,16 @@ glade_project_add_object (GladeProject * project,
gboolean
glade_project_has_object (GladeProject * project, GObject * object)
{
GladeWidget *gwidget;
g_return_val_if_fail (GLADE_IS_PROJECT (project), FALSE);
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
return (g_list_find (project->priv->objects, object)) != NULL;
gwidget = glade_widget_get_from_gobject (object);
g_return_val_if_fail (GLADE_IS_WIDGET (gwidget), FALSE);
return (glade_widget_get_project (gwidget) == project && gwidget->in_project);
}
/**
......@@ -2966,6 +2981,9 @@ glade_project_remove_object (GladeProject * project, GObject * object)
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (G_IS_OBJECT (object));
if (!glade_project_has_object (project, object))
return;
if (GLADE_IS_PLACEHOLDER (object))
return;
......@@ -2994,6 +3012,10 @@ glade_project_remove_object (GladeProject * project, GObject * object)
/* Update internal data structure (remove from lists) */
project->priv->tree = g_list_remove (project->priv->tree, object);
project->priv->objects = g_list_remove (project->priv->objects, object);
/* Unset the project pointer on the GladeWidget */
glade_widget_set_project (gwidget, NULL);
gwidget->in_project = FALSE;
g_object_unref (gwidget);
glade_project_update_previewable (project);
......@@ -3266,7 +3288,7 @@ glade_project_selection_add (GladeProject * project,
{
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (g_list_find (project->priv->objects, object) != NULL);
g_return_if_fail (glade_project_has_object (project, object));
if (glade_project_is_selected (project, object) == FALSE)
{
......@@ -3299,7 +3321,7 @@ glade_project_selection_set (GladeProject * project,
g_return_if_fail (GLADE_IS_PROJECT (project));
g_return_if_fail (G_IS_OBJECT (object));
if (g_list_find (project->priv->objects, object) == NULL)
if (!glade_project_has_object (project, object))
return;
if (project->priv->selection == NULL)
......
......@@ -305,6 +305,7 @@ glade_property_set_value_impl (GladeProperty * property, const GValue * value)
glade_property_signals[VALUE_CHANGED],
0, &old_value, property->value);
glade_project_verify_properties (property->widget);
}
......
......@@ -1525,7 +1525,7 @@ glade_util_object_is_loading (GObject * object)
project = glade_widget_get_project (widget);
return glade_project_is_loading (project);
return project && glade_project_is_loading (project);
}
/**
......
......@@ -2288,8 +2288,9 @@ glade_widget_rebuild (GladeWidget * gwidget)
{