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 @@
#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 @@
*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 @@
/* 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 @@
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 @@
compare function is ignored, because it requires an iterator, not a value. For string columns,
utf8_collate is taken into account.
+
+
+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.
+
+
+
+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.
+
@@ -404,6 +433,8 @@
top-level iter search string | 25 | 0.003 | 0.002 | 25 |
top-level linear search double | 25 | n/a | 0.000 | 25 |
top-level linear search string | 25 | n/a | 0.001 | 25 |
+both levels model foreach | 25 | 0.000 | 0.000 | 25 |
+both levels store traverse | 25 | n/a | 0.000 | 25 |
top-level quick sort double | 25 | 0.000 | 0.000 | |
top-level quick sort string | 25 | 0.001 | 0.000 | |
sublevel 1 insert | 25 | 0.000 | 0.000 | |
@@ -422,6 +453,8 @@
top-level iter search string | 100 | 0.034 | 0.027 | 100 |
top-level linear search double | 100 | n/a | 0.000 | 100 |
top-level linear search string | 100 | n/a | 0.015 | 100 |
+both levels model foreach | 100 | 0.003 | 0.003 | 100 |
+both levels store traverse | 100 | n/a | 0.000 | 100 |
top-level quick sort double | 100 | 0.000 | 0.000 | |
top-level quick sort string | 100 | 0.003 | 0.002 | |
sublevel 1 insert | 100 | 0.000 | 0.000 | |
@@ -440,6 +473,8 @@
top-level iter search string | 250 | 0.224 | 0.183 | 250 |
top-level linear search double | 250 | n/a | 0.001 | 250 |
top-level linear search string | 250 | n/a | 0.109 | 250 |
+both levels model foreach | 250 | 0.018 | 0.018 | 250 |
+both levels store traverse | 250 | n/a | 0.001 | 250 |
top-level quick sort double | 250 | 0.001 | 0.000 | |
top-level quick sort string | 250 | 0.009 | 0.008 | |
sublevel 1 insert | 250 | 0.001 | 0.001 | |
@@ -449,7 +484,7 @@
sublevel 1 quick sort double | 250 | 0.002 | 0.000 | |
sublevel 1 quick sort string | 250 | 0.015 | 0.012 | |
- | 500 | | | |
+ | | | | |
top-level insert | 500 | 0.002 | 0.002 | |
top-level set | 500 | 0.003 | 0.002 | |
top-level remove | 500 | 0.002 | 0.001 | |
@@ -458,6 +493,8 @@
top-level iter search string | 500 | 0.909 | 0.722 | 500 |
top-level linear search double | 500 | n/a | 0.005 | 500 |
top-level linear search string | 500 | n/a | 0.443 | 500 |
+both levels model foreach | 500 | 0.077 | 0.076 | 500 |
+both levels store traverse | 500 | n/a | 0.003 | 500 |
top-level quick sort double | 500 | 0.003 | 0.001 | |
top-level quick sort string | 500 | 0.022 | 0.018 | |
sublevel 1 insert | 500 | 0.002 | 0.002 | |
@@ -476,6 +513,8 @@
top-level iter search string | 1000 | 0.370 | 0.273 | 100 |
top-level linear search double | 1000 | n/a | 0.002 | 100 |
top-level linear search string | 1000 | n/a | 0.182 | 100 |
+both levels model foreach | 1000 | 0.033 | 0.030 | 100 |
+both levels store traverse | 1000 | n/a | 0.001 | 100 |
top-level quick sort double | 1000 | 0.007 | 0.002 | |
top-level quick sort string | 1000 | 0.050 | 0.040 | |
sublevel 1 insert | 1000 | 0.006 | 0.004 | |
@@ -494,6 +533,8 @@
top-level iter search string | 2500 | 2.273 | 1.859 | 250 |
top-level linear search double | 2500 | n/a | 0.015 | 250 |
top-level linear search string | 2500 | n/a | 1.137 | 250 |
+both levels model foreach | 2500 | 0.182 | 0.188 | 250 |
+both levels store traverse | 2500 | n/a | 0.009 | 250 |
top-level quick sort double | 2500 | 0.021 | 0.004 | |
top-level quick sort string | 2500 | 0.146 | 0.117 | |
sublevel 1 insert | 2500 | 0.035 | 0.014 | |
@@ -512,6 +553,8 @@
top-level iter search string | 5000 | 8.775 | 7.787 | 500 |
top-level linear search double | 5000 | n/a | 0.060 | 500 |
top-level linear search string | 5000 | n/a | 4.351 | 500 |
+both levels model foreach | 5000 | 0.741 | 0.754 | 500 |
+both levels store traverse | 5000 | n/a | 0.042 | 500 |
top-level quick sort double | 5000 | 0.046 | 0.010 | |
top-level quick sort string | 5000 | 0.325 | 0.264 | |
sublevel 1 insert | 5000 | 0.168 | 0.040 | |
@@ -530,6 +573,8 @@
top-level iter search string | 10000 | 37.555 | 31.020 | 1000 |
top-level linear search double | 10000 | n/a | 0.304 | 1000 |
top-level linear search string | 10000 | n/a | 18.896 | 1000 |
+both levels model foreach | 10000 | 2.969 | 3.136 | 1000 |
+both levels store traverse | 10000 | n/a | 0.238 | 1000 |
top-level quick sort double | 10000 | 0.112 | 0.022 | |
top-level quick sort string | 10000 | 0.720 | 0.580 | |
sublevel 1 insert | 10000 | 1.152 | 0.132 | |
@@ -647,7 +692,7 @@
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), \