]> Pileus Git - ~andy/gtk/blobdiff - tests/testtreechanging.c
Update for some changes to selectable/selected state handling
[~andy/gtk] / tests / testtreechanging.c
index 825caeb22a1d37ebe5a07e5294270d2ed4e83da1..804505cf28e1f8b755ae1237af04e610040886a6 100644 (file)
@@ -13,9 +13,7 @@
  * 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"
@@ -57,6 +55,33 @@ get_rows (GtkTreeView *treeview)
   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.
  */
@@ -83,29 +108,45 @@ tree_model_iter_step (GtkTreeModel *model,
   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);
 }
@@ -115,6 +156,7 @@ add_one (GtkTreeModel *model,
          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 ())
@@ -126,11 +168,12 @@ add_one (GtkTreeModel *model,
     }
 
   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
@@ -175,6 +218,7 @@ expand (GtkTreeView *treeview)
           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;
@@ -212,42 +256,133 @@ collapse (GtkTreeView *treeview)
 
   if (last)
     {
+      log_operation_for_path (last, "collapse");
       gtk_tree_view_collapse_row (treeview, last);
       gtk_tree_path_free (last);
     }
 }
 
 static void
-check_cursor (GtkTreeView *treeview)
+select_ (GtkTreeView *treeview)
 {
-  GtkTreeRowReference *ref = g_object_get_data (G_OBJECT (treeview), "cursor");
-  GtkTreePath *expected, *cursor;
+  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);
+
+  g_object_unref (model);
+}
 
-      expected = gtk_tree_row_reference_get_path (ref);
-      g_assert (expected != NULL);
-      g_assert (gtk_tree_path_compare (expected, cursor) == 0);
+/* sanity checks */
 
-      gtk_tree_path_free (expected);
+static void
+assert_row_reference_is_path (GtkTreeRowReference *ref,
+                              GtkTreePath *path)
+{
+  GtkTreePath *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
@@ -257,7 +392,10 @@ dance (gpointer treeview)
     add_or_delete,
     add_or_delete,
     expand,
-    collapse
+    collapse,
+    select_,
+    unselect,
+    reset_model
   };
   guint i;
 
@@ -267,7 +405,7 @@ dance (gpointer treeview)
 
   check_sanity (treeview);
 
-  return TRUE;
+  return G_SOURCE_CONTINUE;
 }
 
 static void
@@ -289,11 +427,42 @@ cursor_changed_cb (GtkTreeView *treeview,
   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