diff options
author | Christopher James Lahey <clahey@ximian.com> | 2001-03-20 12:43:42 +0800 |
---|---|---|
committer | Chris Lahey <clahey@src.gnome.org> | 2001-03-20 12:43:42 +0800 |
commit | 1510304c2de206313c637d9269b4fb451cb50adb (patch) | |
tree | 391fc87bab4413e5eec82de476d6ca08db2ce27d /widgets/table/e-tree-model.c | |
parent | 0629bbb778bf9634c380067b65a7f62f2f05a676 (diff) | |
download | gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.tar gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.tar.gz gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.tar.bz2 gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.tar.lz gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.tar.xz gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.tar.zst gsoc2013-evolution-1510304c2de206313c637d9269b4fb451cb50adb.zip |
Deal with proxy_node_changed being called on a different root node than
2001-03-19 Christopher James Lahey <clahey@ximian.com>
* e-tree-sorted.c (ets_proxy_node_changed): Deal with
proxy_node_changed being called on a different root node than the
one we have in our tree.
* e-tree-table-adapter.c: Did some general clean up here.
* Merged branch:
2001-03-19 Christopher James Lahey <clahey@ximian.com>
* e-tree-sorted.c (find_child_path): Added this function to allow
us to find paths that have been removed from the source.
(ets_proxy_node_removed): Fixed the memmove here a bit. Call
find_child_path.
* e-tree-table-adapter.c (find_node): Check that the passed in
path isn't NULL.
2001-03-19 Christopher James Lahey <clahey@ximian.com>
* e-table-item.c (eti_reflow): Get width from header object
instead of calculating it ourselves.
* e-table-selection-model.c: Turn off selection saving since it's
so slow.
* e-table.c (e_table_set_state_object): Set the width of the newly
created header object.
* e-tree.c (e_tree_set_state_object): Set the width of the newly
created header object.
(tree_canvas_size_allocate): Don't bother setting the dimensions
of the white background twice.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-table-selection-model.c, e-table-selection-model.h: Made
ETableSelectionModel save the cursor properly across changed
signals if has_save_id is true.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-table-selection-model.c, e-table-selection-model.h: Made
ETableSelectionModel save selection properly across changed
signals if has_save_id is true.
* e-tree-memory.c: A couple of typos.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-tree-memory.c, e-tree-sorted.c: Send pre_changes properly.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-tree-table-adapter.c: Send pre_changes when performing
set_expanded or root_node_set_visible.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-tree-sorted.c (ets_is_expandable): When the API requests
whether the object is expandable and it isn't, make sure to send a
signal when it becomes expandable.
* e-tree-table-adapter.c: Made it so that in a number of cases
where it doesn't need to create an empty hash table node if the
current tree node has no children, it doesn't.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-tree-memory-callbacks.c, e-tree-memory-callbacks.h
(etmc_has_save_id, etmc_get_save_id): Added has_save_id and
get_save_id to the list of methods supported by
e_tree_memory_callbacks.
* e-tree-table-adapter.c, e-tree-table-adapter.h: Added saving of
expanded nodes.
2001-03-18 Christopher James Lahey <clahey@ximian.com>
* e-table-model.c, e-table-model.h (e_table_model_get_save_id):
Changed row_save_id to get_save_id to be consistent with ETree.
* e-tree-model.c, e-tree-model.h: Added "pre_change" signal.
Added has_save_id and get_save_id methods.
* e-tree-sorted.c: Proxy pre_change signal. Implemented
has_save_id and get_save_id. If the base model doesn't provide
has_save_id then we g_strdup_printf the pointer of the base model
ETreePath as the save_id.
* e-tree-table-adapter.c: Proxy pre_change signal. If base model
has_save_id, then use the results of get_save_id as the key for
the hash table of node attributes. Otherwise use the pointer as
before.
2001-03-17 Christopher James Lahey <clahey@ximian.com>
* e-tree-sorted.c (ets_sort_idle): Fixed it so that all nodes get
sorted properly instead of just the top node.
2001-03-17 Christopher James Lahey <clahey@ximian.com>
* e-table-sorting-utils.c (e_table_sorting_utils_tree_sort): Made
tree sorting faster by using a cache.
* e-tree-sorted.c: Added commented out debugging g_prints.
2001-03-17 Christopher James Lahey <clahey@ximian.com>
* e-tree-sorted.c: Switched to using GMemChunks.
2001-03-17 Christopher James Lahey <clahey@ximian.com>
* e-tree-sorted.c (resort_node): Made it so that children of a
node that's being sorted don't send changed signals.
2001-03-17 Christopher James Lahey <clahey@ximian.com>
* e-table-sorting-utils.c, e-table-sorting-utils.h: Switched to
using e_sort and e_search instead of qsort and a linear search.
Added the tree functions e_table_sorting_utils_tree_sort,
e_table_sorting_utils_tree_check_position, and
e_table_sorting_utils_tree_insert.
* e-tree-sorted.c: Made this actually do sorting.
* e-tree-table-adapter.c (etta_proxy_node_changed): The old_size
needs to be the number of visible children + 1 to include the top
node.
* e-tree.c (e_tree_set_state_object): Set the sort_info on the
ETreeSorted when you get a new sort_info.
2001-03-16 Christopher James Lahey <clahey@ximian.com>
* Makefile.am: Added e-tree-sorted.c and e-tree-sorted.h.
* e-table-item.c (eti_realize_cell_views): Only realize the cells
if they're not realized already and if the canvas is realized.
* e-table-sorted.c (ets_proxy_model_cell_changed): Matched the
change to the signature of e_table_sorting_utils_affects_sort.
* e-table-sorting-utils.c, e-table-sorting-utils.h
(e_table_sorting_utils_affects_sort): Changed the signature of
this function to not take the ETableModel source since it doesn't
use it and we need to use this function for ETreeSorted which
doesn't have an ETableModel.
* e-tree-memory.c (etmm_get_expanded_default): Actually implement
the get_expanded_default for this tree.
* e-tree-model.h: Cleaned up the indentation here.
* e-tree-sorted.c, e-tree-sorted.h: New class meant to be used for
sorting trees. It doesn't actually sort yet. It simply acts as
an ETreeProxy which is the hardest part of making ETreeSorted.
* e-tree.c, e-tree.h: Made this use an ETreeSorted.
2001-03-14 Christopher James Lahey <clahey@ximian.com>
* e-table-item.c, e-table-item.h, e-table-selection-model.c,
e-table-selection-model.h, e-table-sorted.c, e-table-sorted.h,
e-table-subset.c, e-table-subset.h, e-table.c, e-table.h: Switch
to handling e_table_model_rows_inserted instead of
e_table_model_row_inserted and e_table_model_rows_deleted instead
of e_table_model_row_deleted.
* e-table-model.c, e-table-model.h: Replaced the signals
"model_row_inserted" and "model_row_deleted" with
"model_rows_inserted" and "model_rows_deleted" so that when
multiple rows are inserted or deleted at the same time they can be
handled properly.
* e-tree-table-adapter.c: Call "model_rows_inserted" and
"model_rows_deleted" instead of "model_changed" when inserting or
deleting multiple rows.
2001-03-14 Christopher James Lahey <clahey@ximian.com>
* e-table-item.c (e_table_item_row_diff): Made this not count the
pixel between rows if it isn't there.
2001-03-14 Christopher James Lahey <clahey@ximian.com>
* e-table-item.c (eti_header_structure_changed): Properly attach &
realize cell views here.
2001-03-13 Christopher James Lahey <clahey@ximian.com>
* e-tree-table-adapter.c (etta_proxy_node_removed): Check that
parent_node and parent aren't NULL before making function calls on
them.
2001-03-13 Christopher James Lahey <clahey@ximian.com>
* e-table-item.c (confirm_height_cache): Fixed a height cache
miscalculation.
* e-tree-table-adapter.c (find_first_child_node): Made the
semantics of this mean that find_first_child_node(adapter, -1)
means return the first node in the tree.
2001-03-13 Christopher James Lahey <clahey@ximian.com>
* e-table-extras.c: Added a "string-integer" comparison function
to the default %ETableExtras so you can do comparisons based on
integer value even if you using strings for the data (this lets
you do editable numbers, for instance.)
* e-table-item.c: Rearranged it a bit so that if you have
draw_grid off it doesn't add space for the horizontal lines, nor
leave them the background color.
* e-table-model.c, e-table-model.h: Added the row_save_id and
has_save_id methods to %ETableModel.
* e-tree.c, e-tree.h: Replaced e_tree_compute_location with
e_tree_get_cell_at.
2001-03-08 Christopher James Lahey <clahey@ximian.com>
* Makefile.am: Added e-table/e-table-utils.c,
e-table/e-tree-memory-callbacks.c, e-table/e-tree-memory.c,
e-table/e-tree-scrolled.c, e-table/e-tree-table-adapter.c, and
e-table/e-tree.c. Removed e-table/e-tree-simple.c. Added
e-table/e-table-utils.h, e-table/e-tree-memory-callbacks.h,
e-table/e-tree-memory.h, e-table/e-tree-scrolled.h,
e-table/e-tree-table-adapter.h, and e-table/e-tree.h. Removed
e-table/e-tree-simple.h.
* e-cell-tree.c: Updated this for the new tree.
* e-table-item.c: Added some redraw requests where appropriate.
* e-table-item.h: Fixed an incorrect class method declaration.
* e-table-model.c, e-table-model.h: Removed
e_table_model_has_sort_group and e_table_model_row_sort_group.
* e-table-scrolled.h: Removed unused headers.
* e-table-simple.c, e-table-simple.h: Rearranged this a bit.
* e-table-sorter.c, e-table-sorting-utils.c,
e-table-sorting-utils.h: Removed sort group stuff. Added the
function e_table_sorting_utils_check_position.
* e-table-utils.c, e-table-utils.h: Utility functions for ETable
and ETree.
* e-table.c: Moved some of the functionality from here to
e-table-utils.c so that it can be reused by ETree.
* e-tree-memory-callbacks.c, e-tree-memory-callbacks.h: Class to
implement an ETreeMemory as callbacks instead of overriding the
class.
* e-tree-memory.c, e-tree-memory.h: ETreeModel that stores a tree
of physical nodes.
* e-tree-model.c, e-tree-model.h: Removed most of the
functionality from here to the classes ETreeMemory and
ETreeTableAdapter. This is now just a simple virtualized tree
class.
* e-tree-scrolled.c, e-tree-scrolled.h: New class. An ETree in an
EScrollFrame.
* e-tree-simple.c: Small change. This is no longer used.
* e-tree-table-adapter.c, e-tree-table-adapter.h: ETableModel that
represents an ETreeModel as a table.
* e-tree.c, e-tree.h: New super class kind of like ETable but for
trees.
End of branch
svn path=/trunk/; revision=8837
Diffstat (limited to 'widgets/table/e-tree-model.c')
-rw-r--r-- | widgets/table/e-tree-model.c | 1755 |
1 files changed, 343 insertions, 1412 deletions
diff --git a/widgets/table/e-tree-model.c b/widgets/table/e-tree-model.c index 0658cef7db..389e37223a 100644 --- a/widgets/table/e-tree-model.c +++ b/widgets/table/e-tree-model.c @@ -4,10 +4,11 @@ * * Author: * Chris Toshok (toshok@ximian.com) + * Chris Lahey <clahey@ximian.com> * * Adapted from the gtree code and ETableModel. * - * (C) 2000 Ximian, Inc. + * (C) 2000, 2001 Ximian, Inc. */ #include <config.h> @@ -27,566 +28,37 @@ #define ETM_CLASS(e) ((ETreeModelClass *)((GtkObject *)e)->klass) -#define PARENT_TYPE E_TABLE_MODEL_TYPE +#define PARENT_TYPE (gtk_object_get_type()) -#define TREEPATH_CHUNK_AREA_SIZE (30 * sizeof (ETreePath)) - -static ETableModel *e_tree_model_parent_class; - -struct ETreeModelPriv { - GMemChunk *node_chunk; - ETreePath *root; - gboolean root_visible; - GArray *row_array; /* used in the mapping between ETable and our tree */ - GHashTable *expanded_state; /* used for loading/saving expanded state */ - GString *sort_group; /* for caching the last sort group info */ - gboolean expanded_default; /* whether nodes are created expanded or collapsed by default */ - gint frozen; -}; - -struct ETreePath { - gboolean expanded; - gboolean expanded_set; - guint visible_descendents; - char *save_id; - ETreePathCompareFunc compare; - gpointer node_data; - - /* parent/child/sibling pointers */ - ETreePath *parent; - ETreePath *next_sibling; - ETreePath *prev_sibling; - ETreePath *first_child; - ETreePath *last_child; - guint32 num_children; -}; +static GtkObjectClass *parent_class; enum { + PRE_CHANGE, NODE_CHANGED, + NODE_DATA_CHANGED, + NODE_COL_CHANGED, NODE_INSERTED, NODE_REMOVED, - NODE_COLLAPSED, - NODE_EXPANDED, LAST_SIGNAL }; static guint e_tree_model_signals [LAST_SIGNAL] = {0, }; -static void add_visible_descendents_to_array (ETreeModel *etm, ETreePath *node, int *row, int *count); - - -/* ETreePath functions */ - -static int -e_tree_path_depth (ETreePath *path) -{ - int depth = 0; - while (path) { - depth ++; - path = path->parent; - } - return depth; -} - -static void -e_tree_path_insert (ETreePath *parent, int position, ETreePath *child) -{ - g_return_if_fail (position <= parent->num_children || position == -1); - - child->parent = parent; - - if (parent->first_child == NULL) - parent->first_child = child; - - if (position == -1 || position == parent->num_children) { - child->prev_sibling = parent->last_child; - if (parent->last_child) - parent->last_child->next_sibling = child; - parent->last_child = child; - } - else { - ETreePath *c; - for (c = parent->first_child; c; c = c->next_sibling) { - if (position == 0) { - child->next_sibling = c; - child->prev_sibling = c->prev_sibling; - - if (child->next_sibling) - child->next_sibling->prev_sibling = child; - if (child->prev_sibling) - child->prev_sibling->next_sibling = child; - - if (parent->first_child == c) - parent->first_child = child; - break; - } - position --; - } - } - - parent->num_children++; -} - -static void -e_tree_path_unlink (ETreePath *path) -{ - ETreePath *parent = path->parent; - - /* unlink first/last child if applicable */ - if (parent) { - if (path == parent->first_child) - parent->first_child = path->next_sibling; - if (path == parent->last_child) - parent->last_child = path->prev_sibling; - - parent->num_children --; - } - - /* unlink prev/next sibling links */ - if (path->next_sibling) - path->next_sibling->prev_sibling = path->prev_sibling; - if (path->prev_sibling) - path->prev_sibling->next_sibling = path->next_sibling; - - path->parent = NULL; - path->next_sibling = NULL; - path->prev_sibling = NULL; -} - -/** - * e_tree_model_node_traverse: - * @model: - * @path: - * @func: - * @data: - * - * - **/ -void -e_tree_model_node_traverse (ETreeModel *model, ETreePath *path, ETreePathFunc func, gpointer data) -{ - ETreePath *child; - - g_return_if_fail (path); - - child = path->first_child; - - while (child) { - ETreePath *next_child = child->next_sibling; - e_tree_model_node_traverse (model, child, func, data); - if (func (model, child, data) == TRUE) - return; - - child = next_child; - } -} - - - -/** - * e_tree_model_freeze: - * @etm: the ETreeModel to freeze. - * - * This function prepares an ETreeModel for a period of much change. - * All signals regarding changes to the tree are deferred until we - * thaw the tree. - * - **/ -void -e_tree_model_freeze(ETreeModel *etm) -{ - ETreeModelPriv *priv = etm->priv; - - priv->frozen ++; -} - -/** - * e_tree_model_thaw: - * @etm: the ETreeModel to thaw. - * - * This function thaws an ETreeModel. All the defered signals can add - * up to a lot, we don't know - so we just emit a model_changed - * signal. - * - **/ -void -e_tree_model_thaw(ETreeModel *etm) -{ - ETreeModelPriv *priv = etm->priv; - - if (priv->frozen > 0) - priv->frozen --; - if (priv->frozen == 0) { - e_table_model_changed(E_TABLE_MODEL(etm)); - } -} - - -/* virtual methods */ - -static void -etree_destroy (GtkObject *object) -{ - ETreeModel *etree = E_TREE_MODEL (object); - ETreeModelPriv *priv = etree->priv; - - /* XXX lots of stuff to free here */ - - if (priv->root) - e_tree_model_node_remove (etree, priv->root); - - g_array_free (priv->row_array, TRUE); - g_hash_table_destroy (priv->expanded_state); - - g_string_free(priv->sort_group, TRUE); - - g_free (priv); - - GTK_OBJECT_CLASS (e_tree_model_parent_class)->destroy (object); -} - -static ETreePath* -etree_get_root (ETreeModel *etm) -{ - ETreeModelPriv *priv = etm->priv; - return priv->root; -} - -static ETreePath* -etree_get_parent (ETreeModel *etm, ETreePath *path) -{ - g_return_val_if_fail (path, NULL); - - return path->parent; -} - -static ETreePath* -etree_get_next (ETreeModel *etm, ETreePath *node) -{ - g_return_val_if_fail (node, NULL); - - return node->next_sibling; -} - -static ETreePath* -etree_get_prev (ETreeModel *etm, ETreePath *node) -{ - g_return_val_if_fail (node, NULL); - - return node->prev_sibling; -} - -static ETreePath* -etree_get_first_child (ETreeModel *etm, ETreePath *node) -{ - g_return_val_if_fail (node, NULL); - - return node->first_child; -} - -static ETreePath* -etree_get_last_child (ETreeModel *etm, ETreePath *node) -{ - g_return_val_if_fail (node, NULL); - - return node->last_child; -} - -static guint -etree_get_children (ETreeModel *etm, ETreePath* node, ETreePath ***paths) -{ - guint n_children; - - g_return_val_if_fail (node, 0); - - n_children = node->num_children; - - if (paths) { - ETreePath *p; - int i = 0; - (*paths) = g_malloc (sizeof (ETreePath*) * n_children); - for (p = node->first_child; p; p = p->next_sibling) { - (*paths)[i++] = p; - } - } - - return n_children; -} - -static gboolean -etree_is_expanded (ETreeModel *etm, ETreePath* node) -{ - g_return_val_if_fail (node, FALSE); - - return node->expanded; -} - -static gboolean -etree_is_visible (ETreeModel *etm, ETreePath* node) -{ - g_return_val_if_fail (node, FALSE); - - for (node = node->parent; node; node = node->parent) { - if (!node->expanded) - return FALSE; - } - - return TRUE; -} - -static void -etree_set_expanded (ETreeModel *etm, ETreePath* node, gboolean expanded) -{ - ETreeModelPriv *priv = etm->priv; - ETreePath *child; - int row; - - g_return_if_fail (node); - - node->expanded_set = TRUE; - - if (node->expanded == expanded) - return; - - if (expanded) { - gboolean allow_expand = TRUE; - e_tree_model_node_expanded (etm, node, &allow_expand); - if (!allow_expand) - return; - } - - node->expanded = expanded; - if (node->save_id) { - g_hash_table_insert (priv->expanded_state, node->save_id, (gpointer)expanded); - } - - /* if the node wasn't visible at present */ - if ((row = e_tree_model_row_of_node (etm, node)) == -1) { - if (!expanded) { - e_tree_model_node_collapsed (etm, node); - } - return; - } - - row++; - - if (expanded) { - ETreePath *parent; - - if (e_tree_model_node_is_visible (etm, node)) { - node->visible_descendents = 0; - for (child = node->first_child; child; - child = child->next_sibling) { - add_visible_descendents_to_array (etm, child, &row, &node->visible_descendents); - } - } - /* now iterate back up the tree, adding to our - ancestors' visible descendents */ - - for (parent = node->parent; parent; parent = parent->parent) { - parent->visible_descendents += node->visible_descendents; - } - } - else { - int i; - ETreePath *parent; - - if (e_tree_model_node_is_visible (etm, node)) { - for (i = 0; i < node->visible_descendents; i ++) { - priv->row_array = g_array_remove_index (priv->row_array, row); - e_table_model_row_deleted (E_TABLE_MODEL (etm), row); - } - } - /* now iterate back up the tree, subtracting from our - ancestors' visible descendents */ - - for (parent = node->parent; parent; parent = parent->parent) { - parent->visible_descendents -= node->visible_descendents; - } - - node->visible_descendents = 0; - - e_tree_model_node_collapsed (etm, node); - } -} - -/** - * e_tree_model_set_expanded_default: - * @etree: The ETreeModel we're setting the default expanded behavior on. - * @expanded: Whether or not newly inserted parent nodes should be expanded by default. - * - * - **/ -void -e_tree_model_show_node (ETreeModel *etm, ETreePath* node) -{ - ETreePath *parent; - - parent = e_tree_model_node_get_parent(etm, node); - if (parent) { - e_tree_model_show_node(etm, parent); - e_tree_model_node_set_expanded(etm, parent, TRUE); - } -} - -void -e_tree_model_set_expanded_default (ETreeModel *etree, - gboolean expanded) -{ - ETreeModelPriv *priv = etree->priv; - - priv->expanded_default = expanded; -} - -/* fairly naive implementation */ -static void -etree_set_expanded_recurse (ETreeModel *etm, ETreePath* node, gboolean expanded) -{ - ETreePath *child; - - e_tree_model_node_set_expanded (etm, node, expanded); - - for (child = node->first_child; child; child = child->next_sibling) - e_tree_model_node_set_expanded_recurse (etm, child, expanded); -} - -static ETreePath * -etree_node_at_row (ETreeModel *etree, int row) -{ - ETreeModelPriv *priv = etree->priv; - - g_return_val_if_fail (row < priv->row_array->len, NULL); - - return g_array_index (priv->row_array, ETreePath*, row); -} - - -/* ETable analogs */ -static void* -etree_value_at (ETreeModel *etm, ETreePath* node, int col) -{ - /* shouldn't be called */ - g_assert (0); - return NULL; -} - -static GdkPixbuf* -etree_icon_at (ETreeModel *etm, ETreePath* node) -{ - /* shouldn't be called */ - g_assert (0); - return NULL; -} - -static void -etree_set_value_at (ETreeModel *etm, ETreePath* node, int col, const void *val) -{ - /* shouldn't be called */ - g_assert (0); -} - -static gboolean -etree_is_editable (ETreeModel *etm, ETreePath* node, int col) -{ - /* shouldn't be called */ - g_assert(0); - return FALSE; -} - - -/* ETable virtual functions we map */ -static int -etable_row_count (ETableModel *etm) -{ - ETreeModel *tree = E_TREE_MODEL (etm); - ETreeModelPriv *priv = tree->priv; - return priv->row_array->len; -} - -static void * -etable_value_at (ETableModel *etm, int col, int row) -{ - ETreeModel *etree = E_TREE_MODEL(etm); - ETreeModelClass *et_class = ETM_CLASS(etm); - ETreePath* node = e_tree_model_node_at_row (etree, row); - - if (node == NULL) - g_warning ("node is NULL for row %d in etable_value_at\n", row); - - if (col == -1) - return node; - else if (col == -2) - return etm; - else - return et_class->value_at (etree, node, col); -} - -static void -etable_set_value_at (ETableModel *etm, int col, int row, const void *val) -{ - ETreeModel *etree = E_TREE_MODEL(etm); - ETreeModelClass *et_class = ETM_CLASS(etm); - ETreePath* node = e_tree_model_node_at_row (etree, row); - - g_return_if_fail (node); - - et_class->set_value_at (etree, node, col, val); -} - -static gboolean -etable_is_cell_editable (ETableModel *etm, int col, int row) -{ - ETreeModel *etree = E_TREE_MODEL(etm); - ETreeModelClass *et_class = ETM_CLASS(etm); - ETreePath* node = e_tree_model_node_at_row (etree, row); - - g_return_val_if_fail (node, FALSE); - - return et_class->is_editable (etree, node, col); -} - -static void -build_sort_group(GString *out, ETreePath *node) -{ - if (node->parent) { - build_sort_group(out, node->parent); - } - g_string_sprintfa(out, "/%p", node); -} - -static const char * -etable_row_sort_group(ETableModel *etm, int row) -{ - ETreeModel *etree = E_TREE_MODEL(etm); - ETreeModelPriv *priv = etree->priv; - ETreePath* node = e_tree_model_node_at_row (etree, row); - - g_return_val_if_fail (node, ""); - - g_string_truncate(priv->sort_group, 0); - if (node) - build_sort_group(priv->sort_group, node); - - return priv->sort_group->str; -} - -static gboolean -etable_has_sort_group(ETableModel *etm) -{ - /* could optimise for the flat &/or unexpanded tree case */ - return TRUE; -} - static void e_tree_model_class_init (GtkObjectClass *klass) { - ETableModelClass *table_class = (ETableModelClass *) klass; ETreeModelClass *tree_class = (ETreeModelClass *) klass; - e_tree_model_parent_class = gtk_type_class (PARENT_TYPE); - - klass->destroy = etree_destroy; + parent_class = gtk_type_class (PARENT_TYPE); + + e_tree_model_signals [PRE_CHANGE] = + gtk_signal_new ("pre_change", + GTK_RUN_LAST, + klass->type, + GTK_SIGNAL_OFFSET (ETreeModelClass, pre_change), + gtk_marshal_NONE__NONE, + GTK_TYPE_NONE, 0); e_tree_model_signals [NODE_CHANGED] = gtk_signal_new ("node_changed", @@ -596,6 +68,22 @@ e_tree_model_class_init (GtkObjectClass *klass) gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + e_tree_model_signals [NODE_DATA_CHANGED] = + gtk_signal_new ("node_data_changed", + GTK_RUN_LAST, + klass->type, + GTK_SIGNAL_OFFSET (ETreeModelClass, node_data_changed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + + e_tree_model_signals [NODE_COL_CHANGED] = + gtk_signal_new ("node_col_changed", + GTK_RUN_LAST, + klass->type, + GTK_SIGNAL_OFFSET (ETreeModelClass, node_col_changed), + gtk_marshal_NONE__POINTER_INT, + GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT); + e_tree_model_signals [NODE_INSERTED] = gtk_signal_new ("node_inserted", GTK_RUN_LAST, @@ -612,66 +100,50 @@ e_tree_model_class_init (GtkObjectClass *klass) gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); - e_tree_model_signals [NODE_COLLAPSED] = - gtk_signal_new ("node_collapsed", - GTK_RUN_LAST, - klass->type, - GTK_SIGNAL_OFFSET (ETreeModelClass, node_collapsed), - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + gtk_object_class_add_signals (klass, e_tree_model_signals, LAST_SIGNAL); - e_tree_model_signals [NODE_EXPANDED] = - gtk_signal_new ("node_expanded", - GTK_RUN_LAST, - klass->type, - GTK_SIGNAL_OFFSET (ETreeModelClass, node_expanded), - gtk_marshal_NONE__POINTER_POINTER, - GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); + tree_class->get_root = NULL; - gtk_object_class_add_signals (klass, e_tree_model_signals, LAST_SIGNAL); + tree_class->get_parent = NULL; + tree_class->get_first_child = NULL; + tree_class->get_last_child = NULL; + tree_class->get_next = NULL; + tree_class->get_prev = NULL; + + tree_class->is_root = NULL; + tree_class->is_expandable = NULL; + tree_class->get_children = NULL; + tree_class->depth = NULL; + + tree_class->icon_at = NULL; + + tree_class->get_expanded_default = NULL; + tree_class->column_count = NULL; - table_class->row_count = etable_row_count; - table_class->value_at = etable_value_at; - table_class->set_value_at = etable_set_value_at; - table_class->is_cell_editable = etable_is_cell_editable; -#if 0 - /* XX need to pass these through */ - table_class->duplicate_value = etable_duplicate_value; - table_class->free_value = etable_free_value; - table_class->initialize_value = etable_initialize_value; - table_class->value_is_empty = etable_value_is_empty; - table_class->value_to_string = etable_value_to_string; - table_class->thaw = etable_thaw; -#endif - - table_class->row_sort_group = etable_row_sort_group; - table_class->has_sort_group = etable_has_sort_group; - - tree_class->get_root = etree_get_root; - tree_class->get_prev = etree_get_prev; - tree_class->get_next = etree_get_next; - tree_class->get_first_child = etree_get_first_child; - tree_class->get_last_child = etree_get_last_child; - tree_class->get_parent = etree_get_parent; - - tree_class->value_at = etree_value_at; - tree_class->icon_at = etree_icon_at; - tree_class->set_value_at = etree_set_value_at; - tree_class->is_editable = etree_is_editable; - - tree_class->get_children = etree_get_children; - tree_class->is_expanded = etree_is_expanded; - tree_class->is_visible = etree_is_visible; - tree_class->set_expanded = etree_set_expanded; - tree_class->set_expanded_recurse = etree_set_expanded_recurse; - tree_class->node_at_row = etree_node_at_row; + tree_class->has_save_id = NULL; + tree_class->get_save_id = NULL; + + tree_class->value_at = NULL; + tree_class->set_value_at = NULL; + tree_class->is_editable = NULL; + + tree_class->duplicate_value = NULL; + tree_class->free_value = NULL; + tree_class->initialize_value = NULL; + tree_class->value_is_empty = NULL; + tree_class->value_to_string = NULL; + + tree_class->pre_change = NULL; + tree_class->node_changed = NULL; + tree_class->node_data_changed = NULL; + tree_class->node_col_changed = NULL; + tree_class->node_inserted = NULL; + tree_class->node_removed = NULL; } static void e_tree_init (GtkObject *object) { - ETreeModel *etree = (ETreeModel *)object; - e_tree_model_construct (etree); } E_MAKE_TYPE(e_tree_model, "ETreeModel", ETreeModel, e_tree_model_class_init, e_tree_init, PARENT_TYPE) @@ -689,136 +161,114 @@ E_MAKE_TYPE(e_tree_model, "ETreeModel", ETreeModel, e_tree_model_class_init, e_t * Return value: **/ void -e_tree_model_node_changed (ETreeModel *tree_model, ETreePath *node) +e_tree_model_pre_change (ETreeModel *tree_model) { - int row; g_return_if_fail (tree_model != NULL); g_return_if_fail (E_IS_TREE_MODEL (tree_model)); - row = e_tree_model_row_of_node (tree_model, node); - if (row != -1) - e_table_model_row_changed (E_TABLE_MODEL (tree_model), row); - gtk_signal_emit (GTK_OBJECT (tree_model), - e_tree_model_signals [NODE_CHANGED], node); + e_tree_model_signals [PRE_CHANGE]); } /** - * e_tree_model_node_inserted: + * e_tree_model_node_changed: * @tree_model: - * @parent_node: - * @inserted_node: + * @node: * * + * + * Return value: **/ void -e_tree_model_node_inserted (ETreeModel *tree_model, - ETreePath *parent_node, - ETreePath *inserted_node) +e_tree_model_node_changed (ETreeModel *tree_model, ETreePath node) { - int row; g_return_if_fail (tree_model != NULL); g_return_if_fail (E_IS_TREE_MODEL (tree_model)); - - row = e_tree_model_row_of_node (tree_model, inserted_node); - if (row != -1) - e_table_model_row_inserted (E_TABLE_MODEL (tree_model), row); gtk_signal_emit (GTK_OBJECT (tree_model), - e_tree_model_signals [NODE_INSERTED], - parent_node, inserted_node); + e_tree_model_signals [NODE_CHANGED], node); } /** - * e_tree_model_node_removed: + * e_tree_model_node_data_changed: * @tree_model: - * @parent_node: - * @removed_node: + * @node: + * * * + * Return value: **/ void -e_tree_model_node_removed (ETreeModel *tree_model, ETreePath *parent_node, ETreePath *removed_node) +e_tree_model_node_data_changed (ETreeModel *tree_model, ETreePath node) { - int row; - g_return_if_fail (tree_model != NULL); g_return_if_fail (E_IS_TREE_MODEL (tree_model)); - - row = e_tree_model_row_of_node (tree_model, removed_node); - if (row != -1) - e_table_model_row_deleted (E_TABLE_MODEL (tree_model), row); gtk_signal_emit (GTK_OBJECT (tree_model), - e_tree_model_signals [NODE_REMOVED], - parent_node, removed_node); + e_tree_model_signals [NODE_DATA_CHANGED], node); } /** - * e_tree_model_node_collapsed: + * e_tree_model_node_col_changed: * @tree_model: * @node: * * + * + * Return value: **/ void -e_tree_model_node_collapsed (ETreeModel *tree_model, ETreePath *node) +e_tree_model_node_col_changed (ETreeModel *tree_model, ETreePath node, int col) { g_return_if_fail (tree_model != NULL); g_return_if_fail (E_IS_TREE_MODEL (tree_model)); gtk_signal_emit (GTK_OBJECT (tree_model), - e_tree_model_signals [NODE_COLLAPSED], - node); + e_tree_model_signals [NODE_COL_CHANGED], node, col); } /** - * e_tree_model_node_expanded: + * e_tree_model_node_inserted: * @tree_model: - * @node: - * @allow_expand: + * @parent_node: + * @inserted_node: * * **/ void -e_tree_model_node_expanded (ETreeModel *tree_model, ETreePath *node, gboolean *allow_expand) +e_tree_model_node_inserted (ETreeModel *tree_model, + ETreePath parent_node, + ETreePath inserted_node) { g_return_if_fail (tree_model != NULL); g_return_if_fail (E_IS_TREE_MODEL (tree_model)); - + gtk_signal_emit (GTK_OBJECT (tree_model), - e_tree_model_signals [NODE_EXPANDED], - node, allow_expand); + e_tree_model_signals [NODE_INSERTED], + parent_node, inserted_node); } - - /** - * e_tree_model_construct: - * @etree: + * e_tree_model_node_removed: + * @tree_model: + * @parent_node: + * @removed_node: * * **/ void -e_tree_model_construct (ETreeModel *etree) +e_tree_model_node_removed (ETreeModel *tree_model, ETreePath parent_node, ETreePath removed_node) { - ETreeModelPriv *priv; - - g_return_if_fail (etree != NULL); - g_return_if_fail (E_IS_TREE_MODEL (etree)); - - priv = g_new0 (ETreeModelPriv, 1); - etree->priv = priv; - - priv->node_chunk = g_mem_chunk_create (ETreePath, TREEPATH_CHUNK_AREA_SIZE, G_ALLOC_AND_FREE); - priv->root = NULL; - priv->root_visible = TRUE; - priv->row_array = g_array_new (FALSE, FALSE, sizeof(ETreePath*)); - priv->expanded_state = g_hash_table_new (g_str_hash, g_str_equal); - priv->sort_group = g_string_new(""); - priv->frozen = 0; + g_return_if_fail (tree_model != NULL); + g_return_if_fail (E_IS_TREE_MODEL (tree_model)); + + gtk_signal_emit (GTK_OBJECT (tree_model), + e_tree_model_signals [NODE_REMOVED], + parent_node, removed_node); } + + /** * e_tree_model_new * @@ -844,124 +294,35 @@ e_tree_model_new () * * return values: the ETreePath corresponding to the root node. */ -ETreePath * +ETreePath e_tree_model_get_root (ETreeModel *etree) { g_return_val_if_fail (etree != NULL, NULL); g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - return ETM_CLASS(etree)->get_root(etree); -} - -/** - * e_tree_model_node_at_row - * @etree: the ETreeModel. - * @row: - * - * XXX docs here. - * - * return values: the ETreePath corresponding to @row. - */ -ETreePath * -e_tree_model_node_at_row (ETreeModel *etree, int row) -{ - g_return_val_if_fail (etree != NULL, NULL); - g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - - return ETM_CLASS(etree)->node_at_row (etree, row); -} - -/** - * e_tree_model_icon_of_node - * @etree: The ETreeModel. - * @path: The ETreePath to the node we're getting the icon of. - * - * XXX docs here. - * - * return values: the GdkPixbuf associated with this node. - */ -GdkPixbuf * -e_tree_model_icon_of_node (ETreeModel *etree, ETreePath *path) -{ - g_return_val_if_fail (etree != NULL, NULL); - g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - - return ETM_CLASS(etree)->icon_at (etree, path); -} - -/** - * e_tree_model_row_of_node - * @etree: The ETreeModel. - * @node: The node whose row we're looking up. - * - * return values: an int. - */ -int -e_tree_model_row_of_node (ETreeModel *etree, ETreePath *node) -{ - ETreeModelPriv *priv; - int i; - - g_return_val_if_fail (etree != NULL, 0); - g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0); - - priv = etree->priv; - for (i = 0; i < priv->row_array->len; i ++) - if (g_array_index (priv->row_array, ETreePath*, i) == node) - return i; - - return -1; -} - -/** - * e_tree_model_root_node_set_visible - * - * return values: none - */ -void -e_tree_model_root_node_set_visible (ETreeModel *etm, gboolean visible) -{ - ETreeModelPriv *priv; - - g_return_if_fail (etm != NULL); - g_return_if_fail (E_IS_TREE_MODEL (etm)); - - priv = etm->priv; - if (visible != priv->root_visible) { - priv->root_visible = visible; - if (priv->root) { - if (visible) { - priv->row_array = g_array_insert_val (priv->row_array, 0, priv->root); - } - else { - ETreePath *root_path = e_tree_model_get_root (etm); - e_tree_model_node_set_expanded (etm, root_path, TRUE); - priv->row_array = g_array_remove_index (priv->row_array, 0); - } - - e_table_model_changed (E_TABLE_MODEL (etm)); - } - } + if (ETM_CLASS(etree)->get_root) + return ETM_CLASS(etree)->get_root(etree); + else + return NULL; } /** - * e_tree_model_root_node_is_visible: - * @etm: + * e_tree_model_node_get_parent: + * @etree: + * @path: * * * * Return value: **/ -gboolean -e_tree_model_root_node_is_visible (ETreeModel *etm) +ETreePath +e_tree_model_node_get_parent (ETreeModel *etree, ETreePath node) { - ETreeModelPriv *priv; - - g_return_val_if_fail (etm != NULL, FALSE); - g_return_val_if_fail (E_IS_TREE_MODEL (etm), FALSE); - - priv = etm->priv; - return priv->root_visible; + g_return_val_if_fail(etree != NULL, NULL); + if (ETM_CLASS(etree)->get_parent) + return ETM_CLASS(etree)->get_parent(etree, node); + else + return NULL; } /** @@ -973,13 +334,16 @@ e_tree_model_root_node_is_visible (ETreeModel *etm) * * Return value: **/ -ETreePath * -e_tree_model_node_get_first_child (ETreeModel *etree, ETreePath *node) +ETreePath +e_tree_model_node_get_first_child (ETreeModel *etree, ETreePath node) { g_return_val_if_fail (etree != NULL, NULL); g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - return ETM_CLASS(etree)->get_first_child(etree, node); + if (ETM_CLASS(etree)->get_first_child) + return ETM_CLASS(etree)->get_first_child(etree, node); + else + return NULL; } /** @@ -991,13 +355,16 @@ e_tree_model_node_get_first_child (ETreeModel *etree, ETreePath *node) * * Return value: **/ -ETreePath * -e_tree_model_node_get_last_child (ETreeModel *etree, ETreePath *node) +ETreePath +e_tree_model_node_get_last_child (ETreeModel *etree, ETreePath node) { g_return_val_if_fail (etree != NULL, NULL); g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - return ETM_CLASS(etree)->get_last_child(etree, node); + if (ETM_CLASS(etree)->get_last_child) + return ETM_CLASS(etree)->get_last_child(etree, node); + else + return NULL; } @@ -1010,13 +377,16 @@ e_tree_model_node_get_last_child (ETreeModel *etree, ETreePath *node) * * Return value: **/ -ETreePath * -e_tree_model_node_get_next (ETreeModel *etree, ETreePath *node) +ETreePath +e_tree_model_node_get_next (ETreeModel *etree, ETreePath node) { g_return_val_if_fail (etree != NULL, NULL); g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - return ETM_CLASS(etree)->get_next(etree, node); + if (ETM_CLASS(etree)->get_next) + return ETM_CLASS(etree)->get_next(etree, node); + else + return NULL; } /** @@ -1028,47 +398,16 @@ e_tree_model_node_get_next (ETreeModel *etree, ETreePath *node) * * Return value: **/ -ETreePath * -e_tree_model_node_get_prev (ETreeModel *etree, ETreePath *node) +ETreePath +e_tree_model_node_get_prev (ETreeModel *etree, ETreePath node) { g_return_val_if_fail (etree != NULL, NULL); g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - return ETM_CLASS(etree)->get_prev(etree, node); -} - -/** - * e_tree_model_node_depth: - * @etree: - * @path: - * - * - * - * Return value: - **/ -guint -e_tree_model_node_depth (ETreeModel *etree, ETreePath *path) -{ - g_return_val_if_fail (etree != NULL, 0); - g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0); - - return e_tree_path_depth (path) - 1; -} - -/** - * e_tree_model_node_get_parent: - * @etree: - * @path: - * - * - * - * Return value: - **/ -ETreePath * -e_tree_model_node_get_parent (ETreeModel *etree, ETreePath *path) -{ - g_return_val_if_fail(etree != NULL, NULL); - return ETM_CLASS(etree)->get_parent(etree, path); + if (ETM_CLASS(etree)->get_prev) + return ETM_CLASS(etree)->get_prev(etree, node); + else + return NULL; } /** @@ -1081,10 +420,14 @@ e_tree_model_node_get_parent (ETreeModel *etree, ETreePath *path) * Return value: **/ gboolean -e_tree_model_node_is_root (ETreeModel *etree, ETreePath *path) +e_tree_model_node_is_root (ETreeModel *etree, ETreePath node) { g_return_val_if_fail(etree != NULL, FALSE); - return (e_tree_model_node_depth (etree, path) == 0); + + if (ETM_CLASS(etree)->is_root) + return ETM_CLASS(etree)->is_root(etree, node); + else + return FALSE; } /** @@ -1097,30 +440,28 @@ e_tree_model_node_is_root (ETreeModel *etree, ETreePath *path) * Return value: **/ gboolean -e_tree_model_node_is_expandable (ETreeModel *etree, ETreePath *path) +e_tree_model_node_is_expandable (ETreeModel *etree, ETreePath node) { g_return_val_if_fail(etree != NULL, FALSE); - return (e_tree_model_node_get_children (etree, path, NULL) > 0); + + if (ETM_CLASS(etree)->is_expandable) + return ETM_CLASS(etree)->is_expandable(etree, node); + else + return FALSE; } -/** - * e_tree_model_node_is_expanded: - * @etree: - * @path: - * - * - * - * Return value: - **/ -gboolean -e_tree_model_node_is_expanded (ETreeModel *etree, ETreePath *path) +guint +e_tree_model_node_get_children (ETreeModel *etree, ETreePath node, ETreePath **nodes) { - g_return_val_if_fail(etree != NULL, FALSE); - return ETM_CLASS(etree)->is_expanded (etree, path); + g_return_val_if_fail(etree != NULL, 0); + if (ETM_CLASS(etree)->get_children) + return ETM_CLASS(etree)->get_children (etree, node, nodes); + else + return 0; } /** - * e_tree_model_node_is_visible: + * e_tree_model_node_depth: * @etree: * @path: * @@ -1128,290 +469,182 @@ e_tree_model_node_is_expanded (ETreeModel *etree, ETreePath *path) * * Return value: **/ -gboolean -e_tree_model_node_is_visible (ETreeModel *etree, ETreePath *path) +guint +e_tree_model_node_depth (ETreeModel *etree, ETreePath node) { - g_return_val_if_fail(etree != NULL, FALSE); - return ETM_CLASS(etree)->is_visible (etree, path); + g_return_val_if_fail (etree != NULL, 0); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0); + + if (ETM_CLASS(etree)->depth) + return ETM_CLASS(etree)->depth(etree, node); + else + return 0; } /** - * e_tree_model_node_set_expanded: - * @etree: - * @path: - * @expanded: - * - * - **/ -void -e_tree_model_node_set_expanded (ETreeModel *etree, ETreePath *path, gboolean expanded) + * e_tree_model_icon_at + * @etree: The ETreeModel. + * @path: The ETreePath to the node we're getting the icon of. + * + * XXX docs here. + * + * return values: the GdkPixbuf associated with this node. + */ +GdkPixbuf * +e_tree_model_icon_at (ETreeModel *etree, ETreePath node) { - g_return_if_fail(etree != NULL); - ETM_CLASS(etree)->set_expanded (etree, path, expanded); + g_return_val_if_fail (etree != NULL, NULL); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); + + if (ETM_CLASS(etree)->icon_at) + return ETM_CLASS(etree)->icon_at (etree, node); + else + return NULL; } /** - * e_tree_model_node_set_expanded_recurse: - * @etree: - * @path: - * @expanded: - * - * - **/ -void -e_tree_model_node_set_expanded_recurse (ETreeModel *etree, ETreePath *path, gboolean expanded) + * e_tree_model_get_expanded_default + * @etree: The ETreeModel. + * + * XXX docs here. + * + * return values: Whether nodes should be expanded by default. + */ +gboolean +e_tree_model_get_expanded_default (ETreeModel *etree) { - g_return_if_fail(etree != NULL); - ETM_CLASS(etree)->set_expanded_recurse (etree, path, expanded); -} + g_return_val_if_fail (etree != NULL, FALSE); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE); -guint -e_tree_model_node_get_children (ETreeModel *etree, ETreePath *path, ETreePath ***paths) -{ - g_return_val_if_fail(etree != NULL, 0); - return ETM_CLASS(etree)->get_children (etree, path, paths); + if (ETM_CLASS(etree)->get_expanded_default) + return ETM_CLASS(etree)->get_expanded_default (etree); + else + return FALSE; } /** - * e_tree_model_node_num_visible_descendents: - * @etm: - * @node: - * - * - * - * Return value: - **/ -guint -e_tree_model_node_num_visible_descendents (ETreeModel *etm, ETreePath *node) + * e_tree_model_column_count + * @etree: The ETreeModel. + * + * XXX docs here. + * + * return values: The number of columns + */ +gint +e_tree_model_column_count (ETreeModel *etree) { - g_return_val_if_fail(node != NULL, 0); - return node->visible_descendents; + g_return_val_if_fail (etree != NULL, 0); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), 0); + + if (ETM_CLASS(etree)->column_count) + return ETM_CLASS(etree)->column_count (etree); + else + return 0; } /** - * e_tree_model_node_get_data: - * @etm: - * @node: - * - * - * - * Return value: - **/ -gpointer -e_tree_model_node_get_data (ETreeModel *etm, ETreePath *node) + * e_tree_model_has_save_id + * @etree: The ETreeModel. + * + * XXX docs here. + * + * return values: Whether this tree has valid save id data. + */ +gboolean +e_tree_model_has_save_id (ETreeModel *etree) { - g_return_val_if_fail (node, NULL); + g_return_val_if_fail (etree != NULL, FALSE); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), FALSE); - return node->node_data; + if (ETM_CLASS(etree)->has_save_id) + return ETM_CLASS(etree)->has_save_id (etree); + else + return FALSE; } /** - * e_tree_model_node_set_data: - * @etm: - * @node: - * @node_data: - * - * - **/ -void -e_tree_model_node_set_data (ETreeModel *etm, ETreePath *node, gpointer node_data) + * e_tree_model_get_save_id + * @etree: The ETreeModel. + * @node: The ETreePath. + * + * XXX docs here. + * + * return values: The save id for this path. + */ +gchar * +e_tree_model_get_save_id (ETreeModel *etree, ETreePath node) { - g_return_if_fail (node); + g_return_val_if_fail (etree != NULL, NULL); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); - node->node_data = node_data; + if (ETM_CLASS(etree)->get_save_id) + return ETM_CLASS(etree)->get_save_id (etree, node); + else + return NULL; } /** - * e_tree_model_node_insert: - * @tree_model: - * @parent_path: - * @position: - * @node_data: - * - * - * - * Return value: - **/ -ETreePath* -e_tree_model_node_insert (ETreeModel *tree_model, - ETreePath *parent_path, - int position, - gpointer node_data) + * e_tree_model_icon_of_node + * @etree: The ETreeModel. + * @path: The ETreePath to the node we're getting the icon of. + * + * XXX docs here. + * + * return values: the GdkPixbuf associated with this node. + */ +void * +e_tree_model_value_at (ETreeModel *etree, ETreePath node, int col) { - ETreeModelPriv *priv; - ETreePath *new_path; - - g_return_val_if_fail(tree_model != NULL, NULL); - - priv = tree_model->priv; - - g_return_val_if_fail (parent_path != NULL || priv->root == NULL, NULL); - - priv = tree_model->priv; - - new_path = g_chunk_new0 (ETreePath, priv->node_chunk); - - new_path->expanded = FALSE; - new_path->node_data = node_data; - - if (parent_path != NULL) { - - if (parent_path->first_child == NULL - && !parent_path->expanded_set) { - e_tree_model_node_set_expanded (tree_model, - parent_path, - priv->expanded_default); - } - - e_tree_path_insert (parent_path, position, new_path); - - if (e_tree_model_node_is_visible (tree_model, new_path)) { - int parent_row, child_offset = 0; - ETreePath *n; - - /* we need to iterate back up to the root, incrementing the number of visible - descendents */ - for (n = parent_path; n; n = n->parent) { - n->visible_descendents ++; - } - - /* determine if we are inserting at the end of this parent */ - if (position == -1 || position == parent_path->num_children) { - position = e_tree_model_node_num_visible_descendents (tree_model, parent_path) - 1; - } else { - /* if we're not inserting at the end of the array, position is the child node we're - inserting at, not the absolute row position - need to count expanded nodes before it too */ - int i = position; - - n = e_tree_model_node_get_first_child(tree_model, parent_path); - while (n != NULL && i > 0) { - child_offset += n->visible_descendents; - n = n->next_sibling; - i--; - } - } - - - /* if the parent is the root, no need to search for its position since it aint there */ - if (parent_path->parent == NULL) { - parent_row = -1; - } else { - parent_row = e_tree_model_row_of_node (tree_model, parent_path); - } - - e_table_model_pre_change(E_TABLE_MODEL(tree_model)); - - priv->row_array = g_array_insert_val (priv->row_array, - parent_row + position + 1 + child_offset, new_path); - - /* only do this if we know a changed signal isn't coming later on */ - if (priv->frozen == 0) - e_table_model_row_inserted (E_TABLE_MODEL(tree_model), parent_row + position + 1 + child_offset); - } - - if (parent_path->compare) - e_tree_model_node_sort (tree_model, parent_path); - } - else { - priv->root = new_path; - if (priv->root_visible) { - priv->row_array = g_array_insert_val (priv->row_array, 0, priv->root); - e_table_model_row_inserted (E_TABLE_MODEL (tree_model), 0); - } - else { - /* need to mark the new node as expanded or - we'll never see it's children */ - new_path->expanded = TRUE; - new_path->expanded_set = TRUE; - } - } - - return new_path; + g_return_val_if_fail (etree != NULL, NULL); + g_return_val_if_fail (E_IS_TREE_MODEL (etree), NULL); + + if (ETM_CLASS(etree)->value_at) + return ETM_CLASS(etree)->value_at (etree, node, col); + else + return NULL; } /** - * e_tree_model_node_insert_id: - * @tree_model: - * @parent_path: - * @position: - * @node_data: - * @save_id: - * - * - * - * Return value: - **/ -ETreePath* -e_tree_model_node_insert_id (ETreeModel *tree_model, - ETreePath *parent_path, - int position, - gpointer node_data, - const char *save_id) + * e_tree_model_icon_of_node + * @etree: The ETreeModel. + * @path: The ETreePath to the node we're getting the icon of. + * + * XXX docs here. + * + * return values: the GdkPixbuf associated with this node. + */ +void +e_tree_model_set_value_at (ETreeModel *etree, ETreePath node, int col, const void *val) { - ETreePath *path; - - g_return_val_if_fail(tree_model != NULL, NULL); - - path = e_tree_model_node_insert (tree_model, parent_path, position, node_data); - - e_tree_model_node_set_save_id (tree_model, path, save_id); + g_return_if_fail (etree != NULL); + g_return_if_fail (E_IS_TREE_MODEL (etree)); - return path; + if (ETM_CLASS(etree)->set_value_at) + ETM_CLASS(etree)->set_value_at (etree, node, col, val); } /** - * e_tree_model_node_insert_before: + * e_tree_model_node_is_editable: * @etree: - * @parent: - * @sibling: - * @node_data: + * @path: * * * * Return value: **/ -ETreePath * -e_tree_model_node_insert_before (ETreeModel *etree, - ETreePath *parent, - ETreePath *sibling, - gpointer node_data) +gboolean +e_tree_model_node_is_editable (ETreeModel *etree, ETreePath node, int col) { - ETreePath *child; - int position = 0; - - g_return_val_if_fail(etree != NULL, NULL); - - for (child = parent->first_child; child; child = child->next_sibling) { - if (child == sibling) - break; - position ++; - } - return e_tree_model_node_insert (etree, parent, position, node_data); -} + g_return_val_if_fail(etree != NULL, FALSE); -/* just blows away child data, doesn't take into account unlinking/etc */ -static void -child_free(ETreeModel *etree, ETreePath *node) -{ - ETreePath *child, *next; - ETreeModelPriv *priv = etree->priv; - - child = node->first_child; - while (child) { - next = child->next_sibling; - child_free(etree, child); - child = next; - } - - if (node->save_id) { - g_hash_table_remove(priv->expanded_state, node->save_id); - g_free(node->save_id); - } - g_chunk_free(node, priv->node_chunk); + if (ETM_CLASS(etree)->is_editable) + return ETM_CLASS(etree)->is_editable(etree, node, col); + else + return FALSE; } /** - * e_tree_model_node_remove: + * e_tree_model_duplicate_value: * @etree: * @path: * @@ -1419,393 +652,91 @@ child_free(ETreeModel *etree, ETreePath *node) * * Return value: **/ -gpointer -e_tree_model_node_remove (ETreeModel *etree, ETreePath *path) +void * +e_tree_model_duplicate_value (ETreeModel *etree, int col, const void *value) { - ETreeModelPriv *priv = etree->priv; - ETreePath *parent = path->parent; - gpointer ret = path->node_data; - int row, visible = 0, base = 0; - gboolean dochanged; - g_return_val_if_fail(etree != NULL, NULL); - /* work out what range of visible rows to remove */ - if (parent) { - if (e_tree_model_node_is_visible(etree, path)) { - base = e_tree_model_row_of_node(etree, path); - visible = path->visible_descendents + 1; - } - } else if (path == priv->root) { - priv->root = NULL; - if (priv->root_visible) { - base = 0; - visible = path->visible_descendents + 1; - } else { - base = 0; - visible = path->visible_descendents; - } - } else { - g_warning("Trying to remove invalid path %p", path); + if (ETM_CLASS(etree)->duplicate_value) + return ETM_CLASS(etree)->duplicate_value(etree, col, value); + else return NULL; - } - - /* unlink this node - we only have to unlink the root node being removed, - since the others are only references from this node */ - e_tree_path_unlink (path); - - /*printf("removing %d nodes from position %d\n", visible, base);*/ - - if (visible > 0) { - /* fix up the parent visible counts */ - for (; parent; parent = parent->parent) { - parent->visible_descendents -= visible; - } - - /* if we have a lot of nodes to remove, then we dont row_deleted each one */ - /* could probably be tuned, but this'll do, since its normally only when we - remove the whole lot do we really care */ - dochanged = (visible > 1000) || (visible > (priv->row_array->len / 4)); - - e_table_model_pre_change(E_TABLE_MODEL (etree)); - - /* and physically remove them */ - if (visible == priv->row_array->len) { - g_array_set_size(priv->row_array, 0); - } else { - memmove(&g_array_index(priv->row_array, ETreePath *, base), - &g_array_index(priv->row_array, ETreePath *, base+visible), - (priv->row_array->len - (base+visible)) * sizeof(ETreePath *)); - g_array_set_size(priv->row_array, priv->row_array->len - visible); - } - - /* tell the system we've removed (these) nodes */ - if (priv->frozen == 0) { - if (dochanged) { - e_table_model_changed(E_TABLE_MODEL(etree)); - } else { - for (row=visible-1;row>=0;row--) { - e_table_model_row_deleted(E_TABLE_MODEL(etree), row+base); - } - } - } - } - - child_free(etree, path); - - return ret; -} - -static void -add_visible_descendents_to_array (ETreeModel *etm, ETreePath *node, int *row, int *count) -{ - ETreeModelPriv *priv = etm->priv; - - /* add a row for this node */ - e_table_model_pre_change(E_TABLE_MODEL (etm)); - priv->row_array = g_array_insert_val (priv->row_array, (*row), node); - if (priv->frozen == 0) - e_table_model_row_inserted (E_TABLE_MODEL (etm), (*row)); - (*row) ++; - (*count) ++; - - /* then loop over its children, calling this routine for each - of them */ - if (node->expanded) { - ETreePath *child; - for (child = node->first_child; child; - child = child->next_sibling) { - add_visible_descendents_to_array (etm, child, row, count); - } - } -} - -static void -save_expanded_state_func (char *key, gboolean expanded, gpointer user_data) -{ - if (expanded) { - xmlNode *root = (xmlNode*)user_data; - xmlNode *node_root = xmlNewNode (NULL, (xmlChar*) "node"); - - xmlAddChild (root, node_root); - xmlNewChild (node_root, NULL, (xmlChar *) "id", (xmlChar*) key); - } } /** - * e_tree_model_save_expanded_state: - * @etm: - * @filename: + * e_tree_model_free_value: + * @etree: + * @path: * * * * Return value: **/ -gboolean -e_tree_model_save_expanded_state (ETreeModel *etm, const char *filename) -{ - xmlDoc *doc; - xmlNode *root; - int fd, rv; - xmlChar *buf; - int buf_size; - ETreeModelPriv *priv = etm->priv; - - g_return_val_if_fail(etm != NULL, FALSE); - - doc = xmlNewDoc ((xmlChar*) "1.0"); - root = xmlNewDocNode (doc, NULL, - (xmlChar *) "expanded_state", - NULL); - xmlDocSetRootElement (doc, root); - - g_hash_table_foreach (priv->expanded_state, - (GHFunc)save_expanded_state_func, - root); - - fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY, 0777); - - xmlDocDumpMemory (doc, &buf, &buf_size); - - if (buf == NULL) { - g_error ("Failed to write %s: xmlBufferCreate() == NULL", filename); - return FALSE; - } - - rv = write (fd, buf, buf_size); - xmlFree (buf); - close (fd); - - if (0 > rv) { - g_error ("Failed to write new %s: %d\n", filename, errno); - unlink (filename); - return FALSE; - } - - return TRUE; -} - -static char * -get_string_value (xmlNode *node, - const char *name) +void +e_tree_model_free_value (ETreeModel *etree, int col, void *value) { - xmlNode *p; - xmlChar *xml_string; - char *retval; - - p = e_xml_get_child_by_name (node, (xmlChar *) name); - if (p == NULL) - return NULL; - - p = e_xml_get_child_by_name (p, (xmlChar *) "text"); - if (p == NULL) /* there's no text between the tags, return the empty string */ - return g_strdup(""); - - xml_string = xmlNodeListGetString (node->doc, p, 1); - retval = g_strdup ((char *) xml_string); - xmlFree (xml_string); + g_return_if_fail(etree != NULL); - return retval; + if (ETM_CLASS(etree)->free_value) + ETM_CLASS(etree)->free_value(etree, col, value); } /** - * e_tree_model_load_expanded_state: - * @etm: - * @filename: + * e_tree_model_initialize_value: + * @etree: + * @path: * * * * Return value: **/ -gboolean -e_tree_model_load_expanded_state (ETreeModel *etm, const char *filename) +void * +e_tree_model_initialize_value (ETreeModel *etree, int col) { - ETreeModelPriv *priv = etm->priv; - xmlDoc *doc; - xmlNode *root; - xmlNode *child; - - g_return_val_if_fail(etm != NULL, FALSE); - - doc = xmlParseFile (filename); - if (!doc) - return FALSE; - - root = xmlDocGetRootElement (doc); - if (root == NULL || strcmp (root->name, "expanded_state")) { - xmlFreeDoc (doc); - return FALSE; - } - - for (child = root->childs; child; child = child->next) { - char *id; - - if (strcmp (child->name, "node")) { - g_warning ("unknown node '%s' in %s", child->name, filename); - continue; - } - - id = get_string_value (child, "id"); - - g_hash_table_insert (priv->expanded_state, id, (gpointer)TRUE); - } - - xmlFreeDoc (doc); + g_return_val_if_fail(etree != NULL, NULL); - return TRUE; + if (ETM_CLASS(etree)->initialize_value) + return ETM_CLASS(etree)->initialize_value(etree, col); + else + return NULL; } - /** - * e_tree_model_node_set_save_id: - * @etm: - * @node: - * @id: + * e_tree_model_value_is_empty: + * @etree: + * @path: * * - **/ -void -e_tree_model_node_set_save_id (ETreeModel *etm, ETreePath *node, const char *id) -{ - char *key; - gboolean expanded_state; - ETreeModelPriv *priv; - - g_return_if_fail(etm != NULL); - g_return_if_fail (E_TREE_MODEL (etm)); - g_return_if_fail (node); - - priv = etm->priv; - - if (g_hash_table_lookup_extended (priv->expanded_state, - id, (gpointer*)&key, (gpointer*)&expanded_state)) { - - e_tree_model_node_set_expanded (etm, node, - expanded_state); - - /* important that this comes after the e_tree_model_node_set_expanded */ - node->save_id = key; - } - else { - node->save_id = g_strdup (id); - - g_hash_table_insert (priv->expanded_state, node->save_id, (gpointer)node->expanded); - } -} - - - -/** - * e_tree_model_node_set_compare_function: - * @tree_model: - * @node: - * @compare: - * * + * Return value: **/ -void -e_tree_model_node_set_compare_function (ETreeModel *tree_model, - ETreePath *node, - ETreePathCompareFunc compare) +gboolean +e_tree_model_value_is_empty (ETreeModel *etree, int col, const void *value) { - gboolean need_sort; - - g_return_if_fail (tree_model != NULL); - g_return_if_fail (E_TREE_MODEL (tree_model)); - g_return_if_fail (node); + g_return_val_if_fail(etree != NULL, TRUE); - need_sort = (compare != node->compare); - - node->compare = compare; - - if (need_sort) - e_tree_model_node_sort (tree_model, node); -} - -typedef struct { - ETreeModel *model; - ETreePath *path; - ETreePathCompareFunc compare; - gboolean was_expanded; -} ETreeSortInfo; - -static gint -e_tree_model_node_compare (ETreeSortInfo *info1, ETreeSortInfo *info2) -{ - return info1->compare (info1->model, info1->path, info2->path); + if (ETM_CLASS(etree)->value_is_empty) + return ETM_CLASS(etree)->value_is_empty(etree, col, value); + else + return TRUE; } /** - * e_tree_model_node_sort: - * @tree_model: - * @node: + * e_tree_model_value_to_string: + * @etree: + * @path: + * * * + * Return value: **/ -void -e_tree_model_node_sort (ETreeModel *tree_model, - ETreePath *node) +char * +e_tree_model_value_to_string (ETreeModel *etree, int col, const void *value) { - int num_nodes = node->num_children; - ETreeSortInfo *sort_info; - int i; - int child_index; - gboolean node_expanded; - ETreeModelPriv *priv = tree_model->priv;; - - node_expanded = e_tree_model_node_is_expanded (tree_model, node); - - g_return_if_fail (tree_model != NULL); - g_return_if_fail (E_TREE_MODEL (tree_model)); - g_return_if_fail (node); - - g_return_if_fail (node->compare); - - if (num_nodes == 0) - return; + g_return_val_if_fail(etree != NULL, g_strdup("")); - e_table_model_pre_change(E_TABLE_MODEL (tree_model)); - - sort_info = g_new (ETreeSortInfo, num_nodes); - - child_index = e_tree_model_row_of_node (tree_model, node) + 1; - - /* collect our info and remove the children */ - for (i = 0; i < num_nodes; i ++) { - sort_info[i].path = node->first_child; - sort_info[i].was_expanded = e_tree_model_node_is_expanded (tree_model, sort_info[i].path); - sort_info[i].model = tree_model; - sort_info[i].compare = node->compare; - - e_tree_model_node_set_expanded(tree_model, sort_info[i].path, FALSE); - if (node_expanded) - priv->row_array = g_array_remove_index (priv->row_array, child_index); - e_tree_path_unlink (sort_info[i].path); - } - - /* sort things */ - qsort (sort_info, num_nodes, sizeof(ETreeSortInfo), (GCompareFunc)e_tree_model_node_compare); - - /* reinsert the children nodes into the tree in the sorted order */ - for (i = 0; i < num_nodes; i ++) { - e_tree_path_insert (node, i, sort_info[i].path); - if (node_expanded) - priv->row_array = g_array_insert_val (priv->row_array, child_index + i, - sort_info[i].path); - } - - /* make another pass expanding the children as needed. - - XXX this used to be in the loop above, but a recent change - (either here or in the etable code) causes an assertion and - a crash */ - for (i = 0; i < num_nodes; i ++) { - e_tree_model_node_set_expanded (tree_model, sort_info[i].path, sort_info[i].was_expanded); - } - - g_free (sort_info); - - if (priv->frozen == 0) - e_table_model_changed (E_TABLE_MODEL (tree_model)); + if (ETM_CLASS(etree)->value_to_string) + return ETM_CLASS(etree)->value_to_string(etree, col, value); + else + return g_strdup(""); } - |