[evolution] ETableState: Add a "specification" construct-only property.



commit 05c04b5512f8e6cc73b7c9ddb78640212cbdd71d
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Jun 26 11:59:40 2013 -0400

    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()

 .../evolution-util/evolution-util-sections.txt     |    1 +
 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 +-
 mail/e-mail-paned-view.c                           |    2 +-
 8 files changed, 145 insertions(+), 50 deletions(-)
---
diff --git a/doc/reference/evolution-util/evolution-util-sections.txt 
b/doc/reference/evolution-util/evolution-util-sections.txt
index 25fada5..d519311 100644
--- a/doc/reference/evolution-util/evolution-util-sections.txt
+++ b/doc/reference/evolution-util/evolution-util-sections.txt
@@ -3933,6 +3933,7 @@ e_table_specification_get_type
 ETableState
 e_table_state_new
 e_table_state_vanilla
+e_table_state_ref_specification
 e_table_state_load_from_file
 e_table_state_load_from_string
 e_table_state_load_from_node
diff --git a/e-util/e-table-specification.c b/e-util/e-table-specification.c
index 713e057..03c160b 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 cbde70b..77903c7 100644
--- a/e-util/e-table-state.c
+++ b/e-util/e-table-state.c
@@ -26,6 +26,7 @@
 
 #include <libedataserver/libedataserver.h>
 
+#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 ("<ETableState>\n");
-       for (i = 0; i < col_count; i++)
-               g_string_append_printf (str, "  <column source=\"%d\"/>\n", i);
+       for (ii = 0; specification->columns[ii] != NULL; ii++)
+               g_string_append_printf (str, "  <column source=\"%d\"/>\n", ii);
        g_string_append (str, "  <grouping></grouping>\n");
        g_string_append (str, "</ETableState>\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 27bda84..cd5d3e9 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 a4c809a..24ee13f 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 d8fb95e..91caea7 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 3f50e28..1dc8f5d 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);
diff --git a/mail/e-mail-paned-view.c b/mail/e-mail-paned-view.c
index 67cf5b9..c491db7 100644
--- a/mail/e-mail-paned-view.c
+++ b/mail/e-mail-paned-view.c
@@ -934,7 +934,7 @@ mail_paned_view_update_view_instance (EMailView *view)
                                spec, spec_filename);
                        g_free (spec_filename);
 
-                       state = e_table_state_new ();
+                       state = e_table_state_new (spec);
                        view = gal_view_etable_new (spec, "");
 
                        e_table_state_load_from_file (


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]