From 05c04b5512f8e6cc73b7c9ddb78640212cbdd71d Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 26 Jun 2013 11:59:40 -0400 Subject: ETableState: Add a "specification" construct-only property. ETableState now keeps a weak reference on the ETableSpecification to which it's associated. The plan is to replace the column index numbers with a direct reference to an ETableColumnSpecification from the spec. New functions: e_table_state_ref_specification() --- e-util/e-table-specification.c | 31 +++++----- e-util/e-table-state.c | 125 ++++++++++++++++++++++++++++++++++++----- e-util/e-table-state.h | 9 ++- e-util/e-table.c | 10 ++-- e-util/e-tree.c | 8 +-- e-util/gal-view-etable.c | 9 +-- 6 files changed, 143 insertions(+), 49 deletions(-) (limited to 'e-util') diff --git a/e-util/e-table-specification.c b/e-util/e-table-specification.c index 713e0575d5..03c160ba74 100644 --- a/e-util/e-table-specification.c +++ b/e-util/e-table-specification.c @@ -187,8 +187,8 @@ e_table_specification_load_from_node (ETableSpecification *specification, { gchar *temp; xmlNode *children; - GList *list = NULL, *list2; - gint i; + GQueue columns = G_QUEUE_INIT; + guint ii = 0; specification->no_headers = e_xml_get_bool_prop_by_name (node, (const guchar *)"no-headers"); specification->click_to_add = e_xml_get_bool_prop_by_name (node, (const guchar *)"click-to-add"); @@ -244,8 +244,8 @@ e_table_specification_load_from_node (ETableSpecification *specification, g_object_unref (specification->state); specification->state = NULL; if (specification->columns) { - for (i = 0; specification->columns[i]; i++) { - g_object_unref (specification->columns[i]); + for (ii = 0; specification->columns[ii] != NULL; ii++) { + g_object_unref (specification->columns[ii]); } g_free (specification->columns); } @@ -256,24 +256,23 @@ e_table_specification_load_from_node (ETableSpecification *specification, ETableColumnSpecification *col_spec = e_table_column_specification_new (); e_table_column_specification_load_from_node (col_spec, children); - list = g_list_append (list, col_spec); + g_queue_push_tail (&columns, col_spec); } else if (specification->state == NULL && !strcmp ((gchar *) children->name, "ETableState")) { - specification->state = e_table_state_new (); + specification->state = e_table_state_new (specification); e_table_state_load_from_node (specification->state, children); e_table_sort_info_set_can_group (specification->state->sort_info, specification->allow_grouping); } } - if (specification->state == NULL) { - /* Make the default state. */ - specification->state = e_table_state_vanilla (g_list_length (list)); - } + ii = 0; + specification->columns = g_new0 ( + ETableColumnSpecification *, + g_queue_get_length (&columns) + 1); + while (!g_queue_is_empty (&columns)) + specification->columns[ii++] = g_queue_pop_head (&columns); - specification->columns = g_new (ETableColumnSpecification *, g_list_length (list) + 1); - for (list2 = list, i = 0; list2; list2 = g_list_next (list2), i++) { - specification->columns[i] = list2->data; - } - specification->columns[i] = NULL; - g_list_free (list); + /* e_table_state_vanilla() uses the columns array we just created. */ + if (specification->state == NULL) + specification->state = e_table_state_vanilla (specification); } diff --git a/e-util/e-table-state.c b/e-util/e-table-state.c index cbde70b554..77903c7ac8 100644 --- a/e-util/e-table-state.c +++ b/e-util/e-table-state.c @@ -26,6 +26,7 @@ #include +#include "e-table-specification.h" #include "e-xml-utils.h" #define E_TABLE_STATE_GET_PRIVATE(obj) \ @@ -35,17 +36,67 @@ #define STATE_VERSION 0.1 struct _ETableStatePrivate { - gint placeholder; + GWeakRef specification; +}; + +enum { + PROP_0, + PROP_SPECIFICATION }; G_DEFINE_TYPE (ETableState, e_table_state, G_TYPE_OBJECT) +static void +table_state_set_specification (ETableState *state, + ETableSpecification *specification) +{ + g_return_if_fail (E_IS_TABLE_SPECIFICATION (specification)); + + g_weak_ref_set (&state->priv->specification, specification); +} + +static void +table_state_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SPECIFICATION: + table_state_set_specification ( + E_TABLE_STATE (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +table_state_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_SPECIFICATION: + g_value_take_object ( + value, + e_table_state_ref_specification ( + E_TABLE_STATE (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + static void table_state_dispose (GObject *object) { ETableState *state = E_TABLE_STATE (object); g_clear_object (&state->sort_info); + g_weak_ref_set (&state->priv->specification, NULL); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_table_state_parent_class)->dispose (object); @@ -83,9 +134,23 @@ e_table_state_class_init (ETableStateClass *class) g_type_class_add_private (class, sizeof (ETableStatePrivate)); object_class = G_OBJECT_CLASS (class); + object_class->set_property = table_state_set_property; + object_class->get_property = table_state_get_property; object_class->dispose = table_state_dispose; object_class->finalize = table_state_finalize; object_class->constructed = table_state_constructed; + + g_object_class_install_property ( + object_class, + PROP_SPECIFICATION, + g_param_spec_object ( + "specification", + "Table Specification", + "Specification for the table state", + E_TYPE_TABLE_SPECIFICATION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); } static void @@ -95,29 +160,56 @@ e_table_state_init (ETableState *state) } ETableState * -e_table_state_new (void) +e_table_state_new (ETableSpecification *specification) { - return g_object_new (E_TYPE_TABLE_STATE, NULL); + g_return_val_if_fail (E_IS_TABLE_SPECIFICATION (specification), NULL); + + return g_object_new ( + E_TYPE_TABLE_STATE, + "specification", specification, NULL); } ETableState * -e_table_state_vanilla (gint col_count) +e_table_state_vanilla (ETableSpecification *specification) { + ETableState *state; GString *str; - gint i; - ETableState *res; + gint ii; + + g_return_val_if_fail (E_IS_TABLE_SPECIFICATION (specification), NULL); + g_return_val_if_fail (specification->columns != NULL, NULL); str = g_string_new ("\n"); - for (i = 0; i < col_count; i++) - g_string_append_printf (str, " \n", i); + for (ii = 0; specification->columns[ii] != NULL; ii++) + g_string_append_printf (str, " \n", ii); g_string_append (str, " \n"); g_string_append (str, "\n"); - res = e_table_state_new (); - e_table_state_load_from_string (res, str->str); + state = e_table_state_new (specification); + e_table_state_load_from_string (state, str->str); g_string_free (str, TRUE); - return res; + + return state; +} + +/** + * e_table_state_ref_specification: + * @state: an #ETableState + * + * Returns the #ETableSpecification passed to e_table_state_new(). + * + * The returned #ETableSpecification is referenced for thread-safety and must + * be unreferenced with g_object_unref() when finished with it. + * + * Returns: an #ETableSpecification + **/ +ETableSpecification * +e_table_state_ref_specification (ETableState *state) +{ + g_return_val_if_fail (E_IS_TABLE_STATE (state), NULL); + + return g_weak_ref_get (&state->priv->specification); } gboolean @@ -317,19 +409,22 @@ ETableState * e_table_state_duplicate (ETableState *state) { ETableState *new_state; + ETableSpecification *specification; + gboolean can_group; gchar *copy; g_return_val_if_fail (E_IS_TABLE_STATE (state), NULL); - new_state = e_table_state_new (); + specification = e_table_state_ref_specification (state); + new_state = e_table_state_new (specification); + g_object_unref (specification); copy = e_table_state_save_to_string (state); e_table_state_load_from_string (new_state, copy); g_free (copy); - e_table_sort_info_set_can_group - (new_state->sort_info, - e_table_sort_info_get_can_group (state->sort_info)); + can_group = e_table_sort_info_get_can_group (state->sort_info); + e_table_sort_info_set_can_group (new_state->sort_info, can_group); return new_state; } diff --git a/e-util/e-table-state.h b/e-util/e-table-state.h index 27bda8440e..cd5d3e97fe 100644 --- a/e-util/e-table-state.h +++ b/e-util/e-table-state.h @@ -48,6 +48,9 @@ G_BEGIN_DECLS +/* Avoid a circular dependency. */ +struct _ETableSpecification; + typedef struct _ETableState ETableState; typedef struct _ETableStateClass ETableStateClass; typedef struct _ETableStatePrivate ETableStatePrivate; @@ -67,8 +70,10 @@ struct _ETableStateClass { }; GType e_table_state_get_type (void) G_GNUC_CONST; -ETableState * e_table_state_new (void); -ETableState * e_table_state_vanilla (gint col_count); +ETableState * e_table_state_new (struct _ETableSpecification *specification); +ETableState * e_table_state_vanilla (struct _ETableSpecification *specification); +struct _ETableSpecification * + e_table_state_ref_specification (ETableState *state); gboolean e_table_state_load_from_file (ETableState *state, const gchar *filename); void e_table_state_load_from_string (ETableState *state, diff --git a/e-util/e-table.c b/e-util/e-table.c index a4c809a99c..24ee13f38c 100644 --- a/e-util/e-table.c +++ b/e-util/e-table.c @@ -1625,7 +1625,7 @@ e_table_set_state (ETable *e_table, g_return_if_fail (E_IS_TABLE (e_table)); g_return_if_fail (state_str != NULL); - state = e_table_state_new (); + state = e_table_state_new (e_table->spec); e_table_state_load_from_string (state, state_str); if (state->col_count > 0) @@ -1651,7 +1651,7 @@ e_table_load_state (ETable *e_table, g_return_if_fail (E_IS_TABLE (e_table)); g_return_if_fail (filename != NULL); - state = e_table_state_new (); + state = e_table_state_new (e_table->spec); e_table_state_load_from_file (state, filename); if (state->col_count > 0) @@ -1677,7 +1677,7 @@ e_table_get_state_object (ETable *e_table) gint full_col_count; gint i, j; - state = e_table_state_new (); + state = e_table_state_new (e_table->spec); if (state->sort_info) g_object_unref (state->sort_info); state->sort_info = e_table->sort_info; @@ -1924,7 +1924,7 @@ e_table_construct (ETable *e_table, } if (state_str) { - state = e_table_state_new (); + state = e_table_state_new (specification); g_object_ref (state); e_table_state_load_from_string (state, state_str); if (state->col_count <= 0) { @@ -1982,7 +1982,7 @@ e_table_construct_from_spec_file (ETable *e_table, } if (state_fn) { - state = e_table_state_new (); + state = e_table_state_new (specification); if (!e_table_state_load_from_file (state, state_fn)) { g_object_unref (state); state = specification->state; diff --git a/e-util/e-tree.c b/e-util/e-tree.c index d8fb95e6d2..91caea7c43 100644 --- a/e-util/e-tree.c +++ b/e-util/e-tree.c @@ -1355,7 +1355,7 @@ e_tree_set_state (ETree *tree, g_return_if_fail (E_IS_TREE (tree)); g_return_if_fail (state_str != NULL); - state = e_table_state_new (); + state = e_table_state_new (tree->priv->spec); e_table_state_load_from_string (state, state_str); if (state->col_count > 0) @@ -1381,7 +1381,7 @@ e_tree_get_state_object (ETree *tree) gint full_col_count; gint i, j; - state = e_table_state_new (); + state = e_table_state_new (tree->priv->spec); state->sort_info = tree->priv->sort_info; if (state->sort_info) g_object_ref (state->sort_info); @@ -1646,7 +1646,7 @@ e_tree_construct (ETree *tree, return FALSE; } if (state_str) { - state = e_table_state_new (); + state = e_table_state_new (specification); e_table_state_load_from_string (state, state_str); if (state->col_count <= 0) { g_object_unref (state); @@ -1707,7 +1707,7 @@ e_tree_construct_from_spec_file (ETree *tree, return FALSE; } if (state_fn) { - state = e_table_state_new (); + state = e_table_state_new (specification); if (!e_table_state_load_from_file (state, state_fn)) { g_object_unref (state); state = specification->state; diff --git a/e-util/gal-view-etable.c b/e-util/gal-view-etable.c index 3f50e2881a..1dc8f5d357 100644 --- a/e-util/gal-view-etable.c +++ b/e-util/gal-view-etable.c @@ -137,13 +137,10 @@ gal_view_etable_clone (GalView *view) gve = GAL_VIEW_ETABLE (view); new = g_object_new (GAL_TYPE_VIEW_ETABLE, NULL); - new->spec = gve->spec; + new->spec = g_object_ref (gve->spec); new->title = g_strdup (gve->title); - g_object_unref (new->state); new->state = e_table_state_duplicate (gve->state); - g_object_ref (new->spec); - return GAL_VIEW (new); } @@ -189,9 +186,6 @@ gal_view_etable_class_init (GalViewEtableClass *class) static void gal_view_etable_init (GalViewEtable *gve) { - gve->spec = NULL; - gve->state = e_table_state_new (); - gve->title = NULL; } /** @@ -237,6 +231,7 @@ gal_view_etable_construct (GalViewEtable *view, g_return_val_if_fail (E_IS_TABLE_SPECIFICATION (spec), NULL); view->spec = g_object_ref (spec); + view->state = e_table_state_new (spec); if (view->state) g_object_unref (view->state); -- cgit v1.2.3