* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "prop-editor.h"
return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (treeview), "rows"));
}
+static void
+log_operation_for_path (GtkTreePath *path,
+ const char *operation_name)
+{
+ char *path_string;
+
+ path_string = path ? gtk_tree_path_to_string (path) : g_strdup ("");
+
+ g_printerr ("%10s %s\n", operation_name, path_string);
+
+ g_free (path_string);
+}
+
+static void
+log_operation (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ const char *operation_name)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (model, iter);
+
+ log_operation_for_path (path, operation_name);
+
+ gtk_tree_path_free (path);
+}
+
/* moves iter to the next iter in the model in the display order
* inside a treeview. Returns FALSE if no more rows exist.
*/
return FALSE;
}
+/* NB: may include invisible iters (because they are collapsed) */
static void
-delete (GtkTreeView *treeview)
+tree_view_random_iter (GtkTreeView *treeview,
+ GtkTreeIter *iter)
{
guint n_rows = get_rows (treeview);
guint i = g_random_int_range (0, n_rows);
GtkTreeModel *model;
- GtkTreeIter iter;
model = gtk_tree_view_get_model (treeview);
- if (!gtk_tree_model_get_iter_first (model, &iter))
+ if (!gtk_tree_model_get_iter_first (model, iter))
return;
while (i-- > 0)
{
- if (!tree_model_iter_step (model, &iter))
+ if (!tree_model_iter_step (model, iter))
{
g_assert_not_reached ();
return;
}
}
+ return;
+}
+
+static void
+delete (GtkTreeView *treeview)
+{
+ guint n_rows = get_rows (treeview);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ model = gtk_tree_view_get_model (treeview);
+
+ tree_view_random_iter (treeview, &iter);
+
n_rows -= count_children (model, &iter) + 1;
+ log_operation (model, &iter, "remove");
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
set_rows (treeview, n_rows);
}
GtkTreeIter *iter)
{
guint n = gtk_tree_model_iter_n_children (model, iter);
+ GtkTreeIter new_iter;
static guint counter = 0;
if (n > 0 && g_random_boolean ())
}
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
- NULL,
+ &new_iter,
iter,
g_random_int_range (-1, n),
0, ++counter,
-1);
+ log_operation (model, &new_iter, "add");
}
static void
delete (treeview);
}
+/* XXX: We only expand/collapse from the top and not randomly */
static void
-check_cursor (GtkTreeView *treeview)
+expand (GtkTreeView *treeview)
{
- GtkTreeRowReference *ref = g_object_get_data (G_OBJECT (treeview), "cursor");
- GtkTreePath *expected, *cursor;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ gboolean valid;
+
+ model = gtk_tree_view_get_model (treeview);
+
+ for (valid = gtk_tree_model_get_iter_first (model, &iter);
+ valid;
+ valid = tree_model_iter_step (model, &iter))
+ {
+ if (gtk_tree_model_iter_has_child (model, &iter))
+ {
+ path = gtk_tree_model_get_path (model, &iter);
+ if (!gtk_tree_view_row_expanded (treeview, path))
+ {
+ log_operation (model, &iter, "expand");
+ gtk_tree_view_expand_row (treeview, path, FALSE);
+ gtk_tree_path_free (path);
+ return;
+ }
+ gtk_tree_path_free (path);
+ }
+ }
+}
+
+static void
+collapse (GtkTreeView *treeview)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *last, *path;
+ gboolean valid;
+
+ model = gtk_tree_view_get_model (treeview);
+ last = NULL;
+
+ for (valid = gtk_tree_model_get_iter_first (model, &iter);
+ valid;
+ valid = tree_model_iter_step (model, &iter))
+ {
+ path = gtk_tree_model_get_path (model, &iter);
+ if (gtk_tree_view_row_expanded (treeview, path))
+ {
+ if (last)
+ gtk_tree_path_free (last);
+ last = path;
+ }
+ else
+ gtk_tree_path_free (path);
+ }
+
+ if (last)
+ {
+ log_operation_for_path (last, "collapse");
+ gtk_tree_view_collapse_row (treeview, last);
+ gtk_tree_path_free (last);
+ }
+}
+
+static void
+select_ (GtkTreeView *treeview)
+{
+ GtkTreeIter iter;
+
+ tree_view_random_iter (treeview, &iter);
+
+ log_operation (gtk_tree_view_get_model (treeview), &iter, "select");
+ gtk_tree_selection_select_iter (gtk_tree_view_get_selection (treeview),
+ &iter);
+}
+
+static void
+unselect (GtkTreeView *treeview)
+{
+ GtkTreeIter iter;
+ tree_view_random_iter (treeview, &iter);
+
+ log_operation (gtk_tree_view_get_model (treeview), &iter, "unselect");
+ gtk_tree_selection_unselect_iter (gtk_tree_view_get_selection (treeview),
+ &iter);
+}
+
+static void
+reset_model (GtkTreeView *treeview)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GList *list, *selected;
+ GtkTreePath *cursor;
+
+ selection = gtk_tree_view_get_selection (treeview);
+ model = g_object_ref (gtk_tree_view_get_model (treeview));
+
+ log_operation_for_path (NULL, "reset");
+
+ selected = gtk_tree_selection_get_selected_rows (selection, NULL);
gtk_tree_view_get_cursor (treeview, &cursor, NULL);
- if (ref == NULL)
+
+ gtk_tree_view_set_model (treeview, NULL);
+ gtk_tree_view_set_model (treeview, model);
+
+ if (cursor)
{
- g_assert (cursor == NULL);
+ gtk_tree_view_set_cursor (treeview, cursor, NULL, FALSE);
+ gtk_tree_path_free (cursor);
}
- else
+ for (list = selected; list; list = list->next)
{
- g_assert (cursor != NULL);
- g_assert (gtk_tree_row_reference_valid (ref));
+ gtk_tree_selection_select_path (selection, list->data);
+ }
+ g_list_free_full (selected, (GDestroyNotify) gtk_tree_path_free);
- expected = gtk_tree_row_reference_get_path (ref);
- g_assert (expected != NULL);
- g_assert (gtk_tree_path_compare (expected, cursor) == 0);
+ g_object_unref (model);
+}
+
+/* sanity checks */
+
+static void
+assert_row_reference_is_path (GtkTreeRowReference *ref,
+ GtkTreePath *path)
+{
+ GtkTreePath *expected;
- gtk_tree_path_free (expected);
+ if (ref == NULL)
+ {
+ g_assert (path == NULL);
+ return;
}
+ g_assert (path != NULL);
+ g_assert (gtk_tree_row_reference_valid (ref));
+
+ expected = gtk_tree_row_reference_get_path (ref);
+ g_assert (expected != NULL);
+ g_assert (gtk_tree_path_compare (expected, path) == 0);
+ gtk_tree_path_free (expected);
+}
+
+static void
+check_cursor (GtkTreeView *treeview)
+{
+ GtkTreeRowReference *ref = g_object_get_data (G_OBJECT (treeview), "cursor");
+ GtkTreePath *cursor;
+
+ gtk_tree_view_get_cursor (treeview, &cursor, NULL);
+ assert_row_reference_is_path (ref, cursor);
+
if (cursor)
gtk_tree_path_free (cursor);
}
+static void
+check_selection_item (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer listp)
+{
+ GList **list = listp;
+
+ g_assert (*list);
+ assert_row_reference_is_path ((*list)->data, path);
+ *list = (*list)->next;
+}
+
+static void
+check_selection (GtkTreeView *treeview)
+{
+ GList *selection = g_object_get_data (G_OBJECT (treeview), "selection");
+
+ gtk_tree_selection_selected_foreach (gtk_tree_view_get_selection (treeview),
+ check_selection_item,
+ &selection);
+}
+
static void
check_sanity (GtkTreeView *treeview)
{
check_cursor (treeview);
+ check_selection (treeview);
}
static gboolean
{
static const DoStuffFunc funcs[] = {
add_or_delete,
- add_or_delete
+ add_or_delete,
+ expand,
+ collapse,
+ select_,
+ unselect,
+ reset_model
};
+ guint i;
- funcs[g_random_int_range (0, G_N_ELEMENTS(funcs))] (treeview);
+ i = g_random_int_range (0, G_N_ELEMENTS(funcs));
+
+ funcs[i] (treeview);
check_sanity (treeview);
- return TRUE;
+ return G_SOURCE_CONTINUE;
}
static void
g_object_set_data_full (G_OBJECT (treeview), "cursor", ref, (GDestroyNotify) gtk_tree_row_reference_free);
}
+static void
+selection_list_free (gpointer list)
+{
+ g_list_free_full (list, (GDestroyNotify) gtk_tree_row_reference_free);
+}
+
+static void
+selection_changed_cb (GtkTreeSelection *tree_selection,
+ gpointer unused)
+{
+ GList *selected, *list;
+ GtkTreeModel *model;
+
+ selected = gtk_tree_selection_get_selected_rows (tree_selection, &model);
+
+ for (list = selected; list; list = list->next)
+ {
+ GtkTreePath *path = list->data;
+
+ list->data = gtk_tree_row_reference_new (model, path);
+ gtk_tree_path_free (path);
+ }
+
+ g_object_set_data_full (G_OBJECT (gtk_tree_selection_get_tree_view (tree_selection)),
+ "selection",
+ selected,
+ selection_list_free);
+}
+
static void
setup_sanity_checks (GtkTreeView *treeview)
{
g_signal_connect (treeview, "cursor-changed", G_CALLBACK (cursor_changed_cb), NULL);
cursor_changed_cb (treeview, NULL);
+ g_signal_connect (gtk_tree_view_get_selection (treeview), "changed", G_CALLBACK (selection_changed_cb), NULL);
+ selection_changed_cb (gtk_tree_view_get_selection (treeview), NULL);
}
int
gtk_widget_show_all (window);
- g_timeout_add (50, dance, treeview);
+ g_idle_add (dance, treeview);
gtk_main ();