Skip to content

Commit

Permalink
scope - added scp_tree_store_traverse()
Browse files Browse the repository at this point in the history
  • Loading branch information
zhekov committed May 16, 2013
1 parent 1083fee commit d3b344d
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 25 deletions.
8 changes: 7 additions & 1 deletion scope/ChangeLog
@@ -1,3 +1,9 @@
2013-05-16 Dimitar Zhekov <dimitar.zhekov@gmail.com>

* src/store/ChangeLog:
Separate change log for ScpTreeStore - initial release.


2013-05-08 Dimitar Zhekov <dimitar.zhekov@gmail.com>

* src/conterm.c:
Expand All @@ -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 <dimitar.zhekov@gmail.com>
Expand Down
9 changes: 9 additions & 0 deletions scope/src/store/ChangeLog
@@ -0,0 +1,9 @@
2013-05-16 Dimitar Zhekov <dimitar.zhekov@gmail.com>

* 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.
84 changes: 75 additions & 9 deletions scope/src/store/scptreestore.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion scope/src/store/scptreestore.h
Expand Up @@ -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);
Expand Down Expand Up @@ -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

Expand Down
65 changes: 55 additions & 10 deletions scope/src/store/scptreestore.html
Expand Up @@ -55,9 +55,9 @@ <h3><a name="synopsis">Synopsis</a></h3>
#include &quot;scptreestore.h&quot;</p>

<p>/* Store */<br>
ScpTreeStore *<a href="scp_tree_store_new">scp_tree_store_new</a>(gboolean sublevels, gint
ScpTreeStore *<a href="#scp_tree_store_new">scp_tree_store_new</a>(gboolean sublevels, gint
n_columns, ...);<br>
ScpTreeStore *<a href="scp_tree_store_newv">scp_tree_store_newv</a>(gboolean sublevels, gint
ScpTreeStore *<a href="#scp_tree_store_newv">scp_tree_store_newv</a>(gboolean sublevels, gint
n_columns, GType *types);<br>
gboolean scp_tree_store_set_column_types(ScpTreeStore *store, gint n_columns, GType *types);<br>
#define scp_tree_store_set_utf8_collate(store, utf8_collate)
Expand Down Expand Up @@ -85,16 +85,16 @@ <h3><a name="synopsis">Synopsis</a></h3>
*parent, gint position, ...);<br>
#define scp_tree_store_prepend_with_values(store, iter, parent, ...)<br>
#define scp_tree_store_append_with_values(store, iter, parent, ...)<br>
void <a href="scp_tree_store_get_valist">scp_tree_store_get_valist</a>(ScpTreeStore *store,
void <a href="#scp_tree_store_get_valist">scp_tree_store_get_valist</a>(ScpTreeStore *store,
GtkTreeIter *iter, va_list var_args);<br>
void <a href="scp_tree_store_get">scp_tree_store_get</a>(ScpTreeStore *store, GtkTreeIter
void <a href="#scp_tree_store_get">scp_tree_store_get</a>(ScpTreeStore *store, GtkTreeIter
*iter, ...);<br>
gboolean scp_tree_store_is_ancestor(ScpTreeStore *store, GtkTreeIter *iter, GtkTreeIter
*descendant);<br>
gint scp_tree_store_iter_depth(ScpTreeStore *store, GtkTreeIter *iter);<br>
void <a href="scp_tree_store_clear_children">scp_tree_store_clear_children</a>(ScpTreeStore
void <a href="#scp_tree_store_clear_children">scp_tree_store_clear_children</a>(ScpTreeStore
*store, GtkTreeIter *parent, gboolean emit_subsignals);<br>
#define <a href="scp_tree_store_clear">scp_tree_store_clear(store)</a><br>
#define <a href="#scp_tree_store_clear">scp_tree_store_clear(store)</a><br>
gboolean scp_tree_store_iter_is_valid(ScpTreeStore *store, GtkTreeIter *iter);<br>
void scp_tree_store_reorder(ScpTreeStore *store, GtkTreeIter *parent, gint *new_order);<br>
void scp_tree_store_swap(ScpTreeStore *store, GtkTreeIter *a, GtkTreeIter *b);<br>
Expand Down Expand Up @@ -148,7 +148,7 @@ <h3><a name="synopsis">Synopsis</a></h3>
</p>

<p>/* Extra */<br>
void <a href="scp_tree_store_set_allocation">scp_tree_store_set_allocation</a>(ScpTreeStore
void <a href="#scp_tree_store_set_allocation">scp_tree_store_set_allocation</a>(ScpTreeStore
*store, guint toplevel_reserved, guint sublevel_reserved, gboolean sublevel_discard);<br>
gint <a href="#scp_tree_store_compare_func">scp_tree_store_compare_func</a>(ScpTreeStore *store,
GtkTreeIter *a, GtkTreeIter *b, gpointer data);<br>
Expand All @@ -157,7 +157,12 @@ <h3><a name="synopsis">Synopsis</a></h3>
gint scp_tree_store_iter_tell(ScpTreeStore *store, GtkTreeIter *iter);<br>
gboolean <a href="#scp_tree_store_search">scp_tree_store_search</a>(ScpTreeStore *store,
gboolean sublevels, gboolean linear_order, GtkTreeIter *iter, GtkTreeIter *parent, gint column,
...);
...);<br>
typedef gint (*<a href="#ScpTreeStoreTraverseFunc">ScpTreeStoreTraverseFunc</a>)(ScpTreeStore
*store, GtkTreeIter *iter, gpointer gdata);<br>
gboolean <a href="#scp_tree_store_traverse">scp_tree_store_traverse</a>(ScpTreeStore *store,
gboolean sublevels, GtkTreeIter *iter, GtkTreeIter *parent, ScpTreeStoreTraverseFunc func,
gpointer gdata);
</p>

<hr>
Expand Down Expand Up @@ -331,6 +336,30 @@ <h3><a name="scp_tree_store_search">scp_tree_store_search()</a></h3>
compare function is ignored, because it requires an iterator, not a value. For string columns,
utf8_collate is taken into account.</p>

<h3><a name="ScpTreeStoreTraverseFunc">ScpTreeStoreTraverseFunc()</a></h3>

<p><b>gint ScpTreeStoreTraverseFunc(ScpTreeStore *store, GtkTreeIter *iter, gpointer gdata);
</b></p>

<div>The callback function type for scp_tree_store_traverse(). Return values:</div>
<div class="tab"><tt>TRUE</tt> (or another positive value): stop iterating<br>
<tt>FALSE</tt>: continue iterating<br>
<tt>-1</tt> (or another negative value): remove the current element and continue.</div>

<h3><a name="scp_tree_store_traverse">scp_tree_store_traverse()</a></h3>

<p><b>gboolean scp_tree_store_traverse(ScpTreeStore *store, gboolean sublevels, GtkTreeIter
*iter, GtkTreeIter *parent, ScpTreeStoreTraverseFunc func, gpointer gdata);</b></p>

<div>Traverse the rows under parent.</div>
<div class="tab">iter: optional, may be NULL<br>
parent = NULL: traverse the top-level rows.</div>
<br>
<div>Return values:</div>
<div class="tab"><tt>TRUE</tt> and valid iter if func returns <tt>TRUE</tt> (or
another positive value)<br>
<tt>FALSE</tt> and invalid iter otherwise.</div><br>

<hr>

<h3><a name="properties">Properties</a></h3>
Expand Down Expand Up @@ -404,6 +433,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>25</td><td>0.003</td><td>0.002</td><td>25</td></tr>
<tr><td>top-level linear search double</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr>
<tr><td>top-level linear search string</td><td>25</td><td>n/a</td><td>0.001</td><td>25</td></tr>
<tr><td>both levels model foreach</td><td>25</td><td>0.000</td><td>0.000</td><td>25</td></tr>
<tr><td>both levels store traverse</td><td>25</td><td>n/a</td><td>0.000</td><td>25</td></tr>
<tr><td>top-level quick sort double</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>25</td><td>0.001</td><td>0.000</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>25</td><td>0.000</td><td>0.000</td><td></td></tr>
Expand All @@ -422,6 +453,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>100</td><td>0.034</td><td>0.027</td><td>100</td></tr>
<tr><td>top-level linear search double</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr>
<tr><td>top-level linear search string</td><td>100</td><td>n/a</td><td>0.015</td><td>100</td></tr>
<tr><td>both levels model foreach</td><td>100</td><td>0.003</td><td>0.003</td><td>100</td></tr>
<tr><td>both levels store traverse</td><td>100</td><td>n/a</td><td>0.000</td><td>100</td></tr>
<tr><td>top-level quick sort double</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>100</td><td>0.003</td><td>0.002</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>100</td><td>0.000</td><td>0.000</td><td></td></tr>
Expand All @@ -440,6 +473,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>250</td><td>0.224</td><td>0.183</td><td>250</td></tr>
<tr><td>top-level linear search double</td><td>250</td><td>n/a</td><td>0.001</td><td>250</td></tr>
<tr><td>top-level linear search string</td><td>250</td><td>n/a</td><td>0.109</td><td>250</td></tr>
<tr><td>both levels model foreach</td><td>250</td><td>0.018</td><td>0.018</td><td>250</td></tr>
<tr><td>both levels store traverse</td><td>250</td><td>n/a</td><td>0.001</td><td>250</td></tr>
<tr><td>top-level quick sort double</td><td>250</td><td>0.001</td><td>0.000</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>250</td><td>0.009</td><td>0.008</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>250</td><td>0.001</td><td>0.001</td><td></td></tr>
Expand All @@ -449,7 +484,7 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>sublevel 1 quick sort double</td><td>250</td><td>0.002</td><td>0.000</td><td></td></tr>
<tr><td>sublevel 1 quick sort string</td><td>250</td><td>0.015</td><td>0.012</td><td></td></tr>

<tr><td>&nbsp;</td><td>500</td><td></td><td></td><td></td></tr>
<tr><td>&nbsp;</td><td></td><td></td><td></td><td></td></tr>
<tr><td>top-level insert</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr>
<tr><td>top-level set</td><td>500</td><td>0.003</td><td>0.002</td><td></td></tr>
<tr><td>top-level remove</td><td>500</td><td>0.002</td><td>0.001</td><td></td></tr>
Expand All @@ -458,6 +493,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>500</td><td>0.909</td><td>0.722</td><td>500</td></tr>
<tr><td>top-level linear search double</td><td>500</td><td>n/a</td><td>0.005</td><td>500</td></tr>
<tr><td>top-level linear search string</td><td>500</td><td>n/a</td><td>0.443</td><td>500</td></tr>
<tr><td>both levels model foreach</td><td>500</td><td>0.077</td><td>0.076</td><td>500</td></tr>
<tr><td>both levels store traverse</td><td>500</td><td>n/a</td><td>0.003</td><td>500</td></tr>
<tr><td>top-level quick sort double</td><td>500</td><td>0.003</td><td>0.001</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>500</td><td>0.022</td><td>0.018</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>500</td><td>0.002</td><td>0.002</td><td></td></tr>
Expand All @@ -476,6 +513,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>1000</td><td>0.370</td><td>0.273</td><td>100</td></tr>
<tr><td>top-level linear search double</td><td>1000</td><td>n/a</td><td>0.002</td><td>100</td></tr>
<tr><td>top-level linear search string</td><td>1000</td><td>n/a</td><td>0.182</td><td>100</td></tr>
<tr><td>both levels model foreach</td><td>1000</td><td>0.033</td><td>0.030</td><td>100</td></tr>
<tr><td>both levels store traverse</td><td>1000</td><td>n/a</td><td>0.001</td><td>100</td></tr>
<tr><td>top-level quick sort double</td><td>1000</td><td>0.007</td><td>0.002</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>1000</td><td>0.050</td><td>0.040</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>1000</td><td>0.006</td><td>0.004</td><td></td></tr>
Expand All @@ -494,6 +533,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>2500</td><td>2.273</td><td>1.859</td><td>250</td></tr>
<tr><td>top-level linear search double</td><td>2500</td><td>n/a</td><td>0.015</td><td>250</td></tr>
<tr><td>top-level linear search string</td><td>2500</td><td>n/a</td><td>1.137</td><td>250</td></tr>
<tr><td>both levels model foreach</td><td>2500</td><td>0.182</td><td>0.188</td><td>250</td></tr>
<tr><td>both levels store traverse</td><td>2500</td><td>n/a</td><td>0.009</td><td>250</td></tr>
<tr><td>top-level quick sort double</td><td>2500</td><td>0.021</td><td>0.004</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>2500</td><td>0.146</td><td>0.117</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>2500</td><td>0.035</td><td>0.014</td><td></td></tr>
Expand All @@ -512,6 +553,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>5000</td><td>8.775</td><td>7.787</td><td>500</td></tr>
<tr><td>top-level linear search double</td><td>5000</td><td>n/a</td><td>0.060</td><td>500</td></tr>
<tr><td>top-level linear search string</td><td>5000</td><td>n/a</td><td>4.351</td><td>500</td></tr>
<tr><td>both levels model foreach</td><td>5000</td><td>0.741</td><td>0.754</td><td>500</td></tr>
<tr><td>both levels store traverse</td><td>5000</td><td>n/a</td><td>0.042</td><td>500</td></tr>
<tr><td>top-level quick sort double</td><td>5000</td><td>0.046</td><td>0.010</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>5000</td><td>0.325</td><td>0.264</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>5000</td><td>0.168</td><td>0.040</td><td></td></tr>
Expand All @@ -530,6 +573,8 @@ <h3><a name="speed">Speed</a></h3>
<tr><td>top-level iter search string</td><td>10000</td><td>37.555</td><td>31.020</td><td>1000</td></tr>
<tr><td>top-level linear search double</td><td>10000</td><td>n/a</td><td>0.304</td><td>1000</td></tr>
<tr><td>top-level linear search string</td><td>10000</td><td>n/a</td><td>18.896</td><td>1000</td></tr>
<tr><td>both levels model foreach</td><td>10000</td><td>2.969</td><td>3.136</td><td>1000</td></tr>
<tr><td>both levels store traverse</td><td>10000</td><td>n/a</td><td>0.238</td><td>1000</td></tr>
<tr><td>top-level quick sort double</td><td>10000</td><td>0.112</td><td>0.022</td><td></td></tr>
<tr><td>top-level quick sort string</td><td>10000</td><td>0.720</td><td>0.580</td><td></td></tr>
<tr><td>sublevel 1 insert</td><td>10000</td><td>1.152</td><td>0.132</td><td></td></tr>
Expand Down Expand Up @@ -647,7 +692,7 @@ <h3><a name="copyright">Copyright</a></h3>
<p>ScpTreeStore was initially written for the Scope plugin of Geany light IDE, which relies
heavily on stores.</p>

<p><b>ScpTreeStore 0.83, Copyright (C) 2013 Dimitar Toshkov Zhekov</b></p>
<p><b>ScpTreeStore 0.84, Copyright (C) 2013 Dimitar Toshkov Zhekov</b></p>

<p>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
Expand Down
6 changes: 3 additions & 3 deletions scope/src/views.c
Expand Up @@ -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));
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion scope/src/views.h
Expand Up @@ -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), \
Expand Down

0 comments on commit d3b344d

Please sign in to comment.