diff --git a/scope/ChangeLog b/scope/ChangeLog index 4b1512df2..85201cfe0 100644 --- a/scope/ChangeLog +++ b/scope/ChangeLog @@ -1,3 +1,9 @@ +2013-05-16 Dimitar Zhekov + + * src/store/ChangeLog: + Separate change log for ScpTreeStore - initial release. + + 2013-05-08 Dimitar Zhekov * src/conterm.c: @@ -8,7 +14,7 @@ * src/view.c: Small improvements. * docs/scope.html, src/scope.c: - Increased version to 0.87. + Increased version to 0.88. 2013-05-04 Dimitar Zhekov diff --git a/scope/src/store/ChangeLog b/scope/src/store/ChangeLog new file mode 100644 index 000000000..a8a58c1e0 --- /dev/null +++ b/scope/src/store/ChangeLog @@ -0,0 +1,9 @@ +2013-05-16 Dimitar Zhekov + + * scptreestore.c, scptreestore.h: + Added scp_tree_store_traverse(). + Moved scp_tree_store_iter_tell() from Extra to Store, it's required + to insert before/after and move. + * scptreestore.html: + Documentation and speed test results for scp_tree_store_traverse(). + Increased version to 0.84. diff --git a/scope/src/store/scptreestore.c b/scope/src/store/scptreestore.c index 72a047bd1..74c8063e0 100644 --- a/scope/src/store/scptreestore.c +++ b/scope/src/store/scptreestore.c @@ -821,6 +821,15 @@ void scp_tree_store_move(ScpTreeStore *store, GtkTreeIter *iter, gint position) scp_move_element(store, array, iter, position, TRUE); } +gint scp_tree_store_iter_tell(VALIDATE_ONLY ScpTreeStore *store, GtkTreeIter *iter) +{ + g_return_val_if_fail(SCP_IS_TREE_STORE(store), -1); + g_return_val_if_fail(VALID_ITER(iter, store), -1); + g_return_val_if_fail((guint) ITER_INDEX(iter) < ITER_ARRAY(iter)->len, -1); + + return ITER_INDEX(iter); +} + /* Model */ static gint scp_ptr_array_find(GPtrArray *array, AElem *elem) @@ -1531,15 +1540,6 @@ gboolean scp_tree_store_iter_seek(VALIDATE_ONLY ScpTreeStore *store, GtkTreeIter return TRUE; } -gint scp_tree_store_iter_tell(VALIDATE_ONLY ScpTreeStore *store, GtkTreeIter *iter) -{ - g_return_val_if_fail(SCP_IS_TREE_STORE(store), -1); - g_return_val_if_fail(VALID_ITER(iter, store), -1); - g_return_val_if_fail((guint) ITER_INDEX(iter) < ITER_ARRAY(iter)->len, -1); - - return ITER_INDEX(iter); -} - static gint scp_collate_data(const gchar *key, const gchar *data) { gchar *key1 = g_utf8_collate_key(data, -1); @@ -1663,6 +1663,72 @@ gboolean scp_tree_store_search(ScpTreeStore *store, gboolean sublevels, gboolean return found; } +static gboolean scp_traverse(ScpTreeStore *store, GPtrArray *array, GtkTreeIter *iter, + gboolean sublevels, ScpTreeStoreTraverseFunc func, gpointer gdata) +{ + if (array) + { + guint i = 0; + + iter->user_data = array; + iter->user_data2 = GINT_TO_POINTER(0); + + while (i < array->len) + { + gint result = func(store, iter, gdata); + + if (result > 0) + return TRUE; + + if (!result) + { + if (sublevels) + { + if (scp_traverse(store, ((AElem *) array->pdata[i])->children, + iter, TRUE, func, gdata) > 0) + { + return TRUE; + } + + iter->user_data = array; + } + + iter->user_data2 = GINT_TO_POINTER(++i); + } + else + scp_tree_store_remove(store, iter); + } + } + + return FALSE; +} + +gboolean scp_tree_store_traverse(ScpTreeStore *store, gboolean sublevels, GtkTreeIter *iter, + GtkTreeIter *parent, ScpTreeStoreTraverseFunc func, gpointer gdata) +{ + ScpTreeStorePrivate *priv = store->priv; + GtkTreeIter iter1; + + g_return_val_if_fail(SCP_IS_TREE_STORE(store), FALSE); + g_return_val_if_fail(VALID_ITER_OR_NULL(parent, store), FALSE); + g_return_val_if_fail(sublevels == FALSE || priv->sublevels == TRUE, FALSE); + g_return_val_if_fail(func != NULL, FALSE); + + if (!iter) + iter = &iter1; + + iter->stamp = priv->stamp; + + if (!scp_traverse(store, (parent ? ITER_ELEM(parent) : priv->root)->children, iter, + sublevels, func, gdata)) + { + iter->stamp = 0; + return FALSE; + } + + return TRUE; +} + /* Class */ static void scp_tree_store_tree_model_init(GtkTreeModelIface *iface) diff --git a/scope/src/store/scptreestore.h b/scope/src/store/scptreestore.h index 397c7244e..0cdfcc930 100644 --- a/scope/src/store/scptreestore.h +++ b/scope/src/store/scptreestore.h @@ -98,6 +98,7 @@ gboolean scp_tree_store_iter_is_valid(ScpTreeStore *store, GtkTreeIter *iter); void scp_tree_store_reorder(ScpTreeStore *store, GtkTreeIter *parent, gint *new_order); void scp_tree_store_swap(ScpTreeStore *store, GtkTreeIter *a, GtkTreeIter *b); void scp_tree_store_move(ScpTreeStore *store, GtkTreeIter *iter, gint position); +gint scp_tree_store_iter_tell(ScpTreeStore *store, GtkTreeIter *iter); /* Model */ GtkTreeModelFlags scp_tree_store_get_flags(ScpTreeStore *store); @@ -149,9 +150,12 @@ gboolean scp_tree_store_get_utf8_collate(ScpTreeStore *store, gint column); gint scp_tree_store_compare_func(ScpTreeStore *store, GtkTreeIter *a, GtkTreeIter *b, gpointer data); gboolean scp_tree_store_iter_seek(ScpTreeStore *store, GtkTreeIter *iter, gint position); -gint scp_tree_store_iter_tell(ScpTreeStore *store, GtkTreeIter *iter); gboolean scp_tree_store_search(ScpTreeStore *store, gboolean sublevels, gboolean linear_order, GtkTreeIter *iter, GtkTreeIter *parent, gint column, ...); +typedef gint (*ScpTreeStoreTraverseFunc)(ScpTreeStore *store, GtkTreeIter *iter, + gpointer gdata); +gboolean scp_tree_store_traverse(ScpTreeStore *store, gboolean sublevels, GtkTreeIter *iter, + GtkTreeIter *parent, ScpTreeStoreTraverseFunc func, gpointer gdata); G_END_DECLS diff --git a/scope/src/store/scptreestore.html b/scope/src/store/scptreestore.html index c97323e0e..9847db63a 100644 --- a/scope/src/store/scptreestore.html +++ b/scope/src/store/scptreestore.html @@ -55,9 +55,9 @@

Synopsis

#include "scptreestore.h"

/* Store */
-ScpTreeStore *scp_tree_store_new(gboolean sublevels, gint +ScpTreeStore *scp_tree_store_new(gboolean sublevels, gint n_columns, ...);
-ScpTreeStore *scp_tree_store_newv(gboolean sublevels, gint +ScpTreeStore *scp_tree_store_newv(gboolean sublevels, gint n_columns, GType *types);
gboolean scp_tree_store_set_column_types(ScpTreeStore *store, gint n_columns, GType *types);
#define scp_tree_store_set_utf8_collate(store, utf8_collate) @@ -85,16 +85,16 @@

Synopsis

*parent, gint position, ...);
#define scp_tree_store_prepend_with_values(store, iter, parent, ...)
#define scp_tree_store_append_with_values(store, iter, parent, ...)
-void scp_tree_store_get_valist(ScpTreeStore *store, +void scp_tree_store_get_valist(ScpTreeStore *store, GtkTreeIter *iter, va_list var_args);
-void scp_tree_store_get(ScpTreeStore *store, GtkTreeIter +void scp_tree_store_get(ScpTreeStore *store, GtkTreeIter *iter, ...);
gboolean scp_tree_store_is_ancestor(ScpTreeStore *store, GtkTreeIter *iter, GtkTreeIter *descendant);
gint scp_tree_store_iter_depth(ScpTreeStore *store, GtkTreeIter *iter);
-void scp_tree_store_clear_children(ScpTreeStore +void scp_tree_store_clear_children(ScpTreeStore *store, GtkTreeIter *parent, gboolean emit_subsignals);
-#define scp_tree_store_clear(store)
+#define scp_tree_store_clear(store)
gboolean scp_tree_store_iter_is_valid(ScpTreeStore *store, GtkTreeIter *iter);
void scp_tree_store_reorder(ScpTreeStore *store, GtkTreeIter *parent, gint *new_order);
void scp_tree_store_swap(ScpTreeStore *store, GtkTreeIter *a, GtkTreeIter *b);
@@ -148,7 +148,7 @@

Synopsis

/* Extra */
-void scp_tree_store_set_allocation(ScpTreeStore +void scp_tree_store_set_allocation(ScpTreeStore *store, guint toplevel_reserved, guint sublevel_reserved, gboolean sublevel_discard);
gint scp_tree_store_compare_func(ScpTreeStore *store, GtkTreeIter *a, GtkTreeIter *b, gpointer data);
@@ -157,7 +157,12 @@

Synopsis

gint scp_tree_store_iter_tell(ScpTreeStore *store, GtkTreeIter *iter);
gboolean scp_tree_store_search(ScpTreeStore *store, gboolean sublevels, gboolean linear_order, GtkTreeIter *iter, GtkTreeIter *parent, gint column, -...); +...);
+typedef gint (*ScpTreeStoreTraverseFunc)(ScpTreeStore +*store, GtkTreeIter *iter, gpointer gdata);
+gboolean scp_tree_store_traverse(ScpTreeStore *store, +gboolean sublevels, GtkTreeIter *iter, GtkTreeIter *parent, ScpTreeStoreTraverseFunc func, +gpointer gdata);


@@ -331,6 +336,30 @@

scp_tree_store_search()

compare function is ignored, because it requires an iterator, not a value. For string columns, utf8_collate is taken into account.

+

ScpTreeStoreTraverseFunc()

+ +

gint ScpTreeStoreTraverseFunc(ScpTreeStore *store, GtkTreeIter *iter, gpointer gdata); +

+ +
The callback function type for scp_tree_store_traverse(). Return values:
+
TRUE (or another positive value): stop iterating
+FALSE: continue iterating
+-1 (or another negative value): remove the current element and continue.
+ +

scp_tree_store_traverse()

+ +

gboolean scp_tree_store_traverse(ScpTreeStore *store, gboolean sublevels, GtkTreeIter +*iter, GtkTreeIter *parent, ScpTreeStoreTraverseFunc func, gpointer gdata);

+ +
Traverse the rows under parent.
+
iter: optional, may be NULL
+parent = NULL: traverse the top-level rows.
+
+
Return values:
+
TRUE and valid iter if func returns TRUE (or +another positive value)
+FALSE and invalid iter otherwise.

+

Properties

@@ -404,6 +433,8 @@

Speed

top-level iter search string250.0030.00225 top-level linear search double25n/a0.00025 top-level linear search string25n/a0.00125 +both levels model foreach250.0000.00025 +both levels store traverse25n/a0.00025 top-level quick sort double250.0000.000 top-level quick sort string250.0010.000 sublevel 1 insert250.0000.000 @@ -422,6 +453,8 @@

Speed

top-level iter search string1000.0340.027100 top-level linear search double100n/a0.000100 top-level linear search string100n/a0.015100 +both levels model foreach1000.0030.003100 +both levels store traverse100n/a0.000100 top-level quick sort double1000.0000.000 top-level quick sort string1000.0030.002 sublevel 1 insert1000.0000.000 @@ -440,6 +473,8 @@

Speed

top-level iter search string2500.2240.183250 top-level linear search double250n/a0.001250 top-level linear search string250n/a0.109250 +both levels model foreach2500.0180.018250 +both levels store traverse250n/a0.001250 top-level quick sort double2500.0010.000 top-level quick sort string2500.0090.008 sublevel 1 insert2500.0010.001 @@ -449,7 +484,7 @@

Speed

sublevel 1 quick sort double2500.0020.000 sublevel 1 quick sort string2500.0150.012 - 500 +  top-level insert5000.0020.002 top-level set5000.0030.002 top-level remove5000.0020.001 @@ -458,6 +493,8 @@

Speed

top-level iter search string5000.9090.722500 top-level linear search double500n/a0.005500 top-level linear search string500n/a0.443500 +both levels model foreach5000.0770.076500 +both levels store traverse500n/a0.003500 top-level quick sort double5000.0030.001 top-level quick sort string5000.0220.018 sublevel 1 insert5000.0020.002 @@ -476,6 +513,8 @@

Speed

top-level iter search string10000.3700.273100 top-level linear search double1000n/a0.002100 top-level linear search string1000n/a0.182100 +both levels model foreach10000.0330.030100 +both levels store traverse1000n/a0.001100 top-level quick sort double10000.0070.002 top-level quick sort string10000.0500.040 sublevel 1 insert10000.0060.004 @@ -494,6 +533,8 @@

Speed

top-level iter search string25002.2731.859250 top-level linear search double2500n/a0.015250 top-level linear search string2500n/a1.137250 +both levels model foreach25000.1820.188250 +both levels store traverse2500n/a0.009250 top-level quick sort double25000.0210.004 top-level quick sort string25000.1460.117 sublevel 1 insert25000.0350.014 @@ -512,6 +553,8 @@

Speed

top-level iter search string50008.7757.787500 top-level linear search double5000n/a0.060500 top-level linear search string5000n/a4.351500 +both levels model foreach50000.7410.754500 +both levels store traverse5000n/a0.042500 top-level quick sort double50000.0460.010 top-level quick sort string50000.3250.264 sublevel 1 insert50000.1680.040 @@ -530,6 +573,8 @@

Speed

top-level iter search string1000037.55531.0201000 top-level linear search double10000n/a0.3041000 top-level linear search string10000n/a18.8961000 +both levels model foreach100002.9693.1361000 +both levels store traverse10000n/a0.2381000 top-level quick sort double100000.1120.022 top-level quick sort string100000.7200.580 sublevel 1 insert100001.1520.132 @@ -647,7 +692,7 @@

Copyright

ScpTreeStore was initially written for the Scope plugin of Geany light IDE, which relies heavily on stores.

-

ScpTreeStore 0.83, Copyright (C) 2013 Dimitar Toshkov Zhekov

+

ScpTreeStore 0.84, Copyright (C) 2013 Dimitar Toshkov Zhekov

ScpTreeStore is distributed under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any diff --git a/scope/src/views.c b/scope/src/views.c index c45016ad3..d61026458 100644 --- a/scope/src/views.c +++ b/scope/src/views.c @@ -263,7 +263,7 @@ static void on_display_editing_started(G_GNUC_UNUSED GtkCellRenderer *cell, } GtkTreeView *view_connect(const char *name, ScpTreeStore **store, GtkTreeSelection **selection, - const TreeCell *cell_info, const char *window, GObject **display) + const TreeCell *cell_info, const char *window, GObject **display_cell) { guint i; GtkScrolledWindow *scrolled = GTK_SCROLLED_WINDOW(get_widget(window)); @@ -284,11 +284,11 @@ GtkTreeView *view_connect(const char *name, ScpTreeStore **store, GtkTreeSelecti g_signal_connect(cell, "editing-started", G_CALLBACK(on_editing_started), hadjustment); - if (display && i == 0) + if (display_cell && i == 0) { g_signal_connect(cell, "editing-started", G_CALLBACK(on_display_editing_started), *store); - *display = G_OBJECT(cell); + *display_cell = G_OBJECT(cell); } } else diff --git a/scope/src/views.h b/scope/src/views.h index 7003c8f2a..407299ac9 100644 --- a/scope/src/views.h +++ b/scope/src/views.h @@ -64,7 +64,7 @@ typedef struct _TreeCell GtkTreeView *view_create(const char *name, ScpTreeStore **store, GtkTreeSelection **selection); GtkTreeView *view_connect(const char *name, ScpTreeStore **store, GtkTreeSelection **selection, - const TreeCell *cell_info, const char *window, GObject **display); + const TreeCell *cell_info, const char *window, GObject **display_cell); /* note: 2 references to column */ #define view_set_sort_func(store, column, compare) \ scp_tree_store_set_sort_func((store), (column), (GtkTreeIterCompareFunc) (compare), \