* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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 <gtk/gtk.h>
+#include <string.h>
#include "treemodel.h"
#include "gtktreemodelrefcount.h"
signal_monitor_assert_is_empty (monitor);
check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
+
+ g_object_unref (filter);
+ g_object_unref (store);
+ gtk_widget_destroy (tree_view);
}
static void
signal_monitor_assert_is_empty (monitor);
check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
+
+ g_object_unref (filter);
+ g_object_unref (store);
+ gtk_widget_destroy (tree_view);
}
gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
- /* Only the reference on the first node of the root level is kept. */
+ /* The root level and first level remain cached, only the references on the
+ * first nodes of these levels are kept.
+ */
assert_node_ref_count (ref_model, &parent1, 1);
- assert_node_ref_count (ref_model, &parent2, 0);
- assert_node_ref_count (ref_model, &iter_first, 0);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &iter_first, 1);
assert_node_ref_count (ref_model, &iter, 0);
g_object_unref (filter_model);
gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
- /* Only the reference on the first node of the root level is kept. */
+ /* The root level and first level remain cached, only the references on the
+ * first nodes of these levels are kept. Grandparent2 is the parent
+ * of the first level with parent1, so grandparent2 keeps a reference
+ * as well.
+ */
assert_node_ref_count (ref_model, &grandparent1, 1);
- assert_node_ref_count (ref_model, &grandparent2, 0);
- assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &parent1, 1);
assert_node_ref_count (ref_model, &parent2, 0);
assert_node_ref_count (ref_model, &iter_parent1, 0);
assert_node_ref_count (ref_model, &iter_parent2_first, 0);
g_object_unref (ref_model);
}
+static void
+ref_count_filter_row_length_1 (void)
+{
+ GtkTreeIter level1_1;
+ GtkTreeIter level2_1;
+ GtkTreeIter level3_1;
+ GtkTreeIter level4_1;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkTreePath *path;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+
+ /* + level1_1
+ * + level2_1
+ * + level3_1
+ * + level4_1
+ *
+ * Node level1_1 is expanded. This makes that levels 1 and 2 are
+ * visible. Level 3 is cached because its parent is visible. Level 4
+ * is not cached.
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
+
+ assert_entire_model_unreferenced (ref_model);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ path = gtk_tree_path_new_from_indices (0, -1);
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
+ gtk_tree_path_free (path);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 3);
+ assert_node_ref_count (ref_model, &level3_1, 1);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 3);
+ assert_node_ref_count (ref_model, &level3_1, 1);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ /* level3_1 has a visible parent, so the node is kept in the cache. */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 3);
+ assert_node_ref_count (ref_model, &level3_1, 1);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ /* level2_1 has a visible parent, so is kept in the cache. However,
+ * the external reference should be released.
+ */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ gtk_widget_destroy (tree_view);
+ gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+
+ g_object_unref (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 0);
+
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_filter_row_length_1_remove_in_root_level (void)
+{
+ GtkTreeIter level1_1;
+ GtkTreeIter level2_1;
+ GtkTreeIter level3_1;
+ GtkTreeIter level4_1;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkTreePath *path;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+
+ /* + level1_1
+ * + level2_1
+ * + level3_1
+ * + level4_1
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
+
+ assert_entire_model_unreferenced (ref_model);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ path = gtk_tree_path_new_from_indices (0, -1);
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
+ gtk_tree_path_free (path);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 3);
+ assert_node_ref_count (ref_model, &level3_1, 3);
+ assert_node_ref_count (ref_model, &level4_1, 2);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ gtk_widget_destroy (tree_view);
+ gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ g_object_unref (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 0);
+ assert_node_ref_count (ref_model, &level2_1, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_filter_row_length_1_remove_in_child_level (void)
+{
+ GtkTreeIter level1_1;
+ GtkTreeIter level2_1;
+ GtkTreeIter level3_1;
+ GtkTreeIter level4_1;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkTreePath *path;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+
+ /* + level1_1
+ * + level2_1
+ * + level3_1
+ * + level4_1
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
+
+ assert_entire_model_unreferenced (ref_model);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ path = gtk_tree_path_new_from_indices (0, -1);
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
+ gtk_tree_path_free (path);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 3);
+ assert_node_ref_count (ref_model, &level3_1, 3);
+ assert_node_ref_count (ref_model, &level4_1, 2);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 3);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ gtk_widget_destroy (tree_view);
+ gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ g_object_unref (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 0);
+ assert_node_ref_count (ref_model, &level2_1, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_filter_row_length_gt_1 (void)
+{
+ GtkTreeIter level1_1, level1_2;
+ GtkTreeIter level2_1, level2_2;
+ GtkTreeIter level3_1, level3_2;
+ GtkTreeIter level4_1, level4_2;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkTreePath *path;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+
+ /* + level1_1
+ * + level1_2
+ * + level2_1
+ * + level2_2
+ * + level3_1
+ * + level3_2
+ * + level4_1
+ * + level4_2
+ *
+ * Node level1_2 is expanded. This makes that levels 1 and 2 are
+ * visible. Level 3 is cached because its parent is visible. Level 4
+ * is not cached.
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_2, &level1_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_2, &level2_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_2, &level3_2);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_2, 0, TRUE, -1);
+
+ assert_entire_model_unreferenced (ref_model);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ path = gtk_tree_path_new_from_indices (1, -1);
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
+ gtk_tree_path_free (path);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 2);
+ assert_node_ref_count (ref_model, &level2_2, 2);
+ assert_node_ref_count (ref_model, &level3_1, 1);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 2);
+ assert_node_ref_count (ref_model, &level2_2, 2);
+ assert_node_ref_count (ref_model, &level3_1, 1);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 2);
+ assert_node_ref_count (ref_model, &level2_2, 2);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 1);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 2);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 0);
+ assert_node_ref_count (ref_model, &level2_1, 0);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ gtk_widget_destroy (tree_view);
+ gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
+
+ assert_node_ref_count (ref_model, &level1_1, 1);
+
+ g_object_unref (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 0);
+
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_filter_row_length_gt_1_visible_children (void)
+{
+ GtkTreeIter level1_1, level1_2;
+ GtkTreeIter level2_1, level2_2;
+ GtkTreeIter level3_1, level3_2;
+ GtkTreeIter level4_1, level4_2;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkTreePath *path;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+
+ /* + level1_1
+ * + level1_2
+ * + level2_1
+ * + level2_2
+ * + level3_1
+ * + level3_2
+ * + level4_1
+ * + level4_2
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level1_2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level2_2, &level1_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level3_2, &level2_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_2);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &level4_2, &level3_2);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level3_2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level4_2, 0, TRUE, -1);
+
+ assert_entire_model_unreferenced (ref_model);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ path = gtk_tree_path_new_from_indices (1, -1);
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
+ gtk_tree_path_free (path);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 2);
+ assert_node_ref_count (ref_model, &level2_2, 2);
+ assert_node_ref_count (ref_model, &level3_1, 2);
+ assert_node_ref_count (ref_model, &level3_2, 2);
+ assert_node_ref_count (ref_model, &level4_1, 2);
+ assert_node_ref_count (ref_model, &level4_2, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &level1_1, 2);
+ assert_node_ref_count (ref_model, &level1_2, 2);
+ assert_node_ref_count (ref_model, &level2_1, 2);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ gtk_widget_destroy (tree_view);
+ gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
+
+ assert_node_ref_count (ref_model, &level1_1, 1);
+ assert_node_ref_count (ref_model, &level1_2, 1);
+ assert_node_ref_count (ref_model, &level2_1, 1);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ g_object_unref (filter_model);
+
+ assert_node_ref_count (ref_model, &level1_1, 0);
+ assert_node_ref_count (ref_model, &level1_2, 0);
+ assert_node_ref_count (ref_model, &level2_1, 0);
+ assert_node_ref_count (ref_model, &level2_2, 0);
+ assert_node_ref_count (ref_model, &level3_1, 0);
+ assert_node_ref_count (ref_model, &level3_2, 0);
+ assert_node_ref_count (ref_model, &level4_1, 0);
+ assert_node_ref_count (ref_model, &level4_2, 0);
+
+ g_object_unref (ref_model);
+}
+
static void
ref_count_cleanup (void)
{
gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
- /* Only the reference on the first node of the root level is kept. */
+ /* The root level and first level remain cached, only the references on the
+ * first nodes of these levels are kept. Grandparent2 is the parent
+ * of the first level with parent1, so grandparent2 keeps a reference
+ * as well.
+ */
assert_node_ref_count (ref_model, &grandparent1, 1);
- assert_node_ref_count (ref_model, &grandparent2, 0);
- assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &parent1, 1);
assert_node_ref_count (ref_model, &parent2, 0);
assert_node_ref_count (ref_model, &iter_parent1, 0);
assert_node_ref_count (ref_model, &iter_parent2_first, 0);
gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
- /* Only the reference on the first node of the root level is kept. */
+ /* The root level and first level remain cached, only the references on the
+ * first nodes of these levels are kept. Grandparent2 is the parent
+ * of the first level with parent1, so grandparent2 keeps a reference
+ * as well.
+ */
assert_node_ref_count (ref_model, &grandparent1, 1);
- assert_node_ref_count (ref_model, &grandparent2, 0);
- assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &parent1, 1);
g_object_unref (filter_model);
g_object_unref (ref_model);
}
static void
-ref_count_transfer_root_level_reordered (void)
+ref_count_transfer_root_level_remove (void)
{
GtkTreeIter grandparent1, grandparent2, grandparent3;
GtkTreeModel *model;
assert_node_ref_count (ref_model, &grandparent2, 1);
assert_node_ref_count (ref_model, &grandparent3, 1);
- /* gtk_tree_store_move() will emit rows-reordered */
- gtk_tree_store_move_after (GTK_TREE_STORE (model),
- &grandparent1, &grandparent3);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent1);
assert_node_ref_count (ref_model, &grandparent2, 2);
assert_node_ref_count (ref_model, &grandparent3, 1);
- assert_node_ref_count (ref_model, &grandparent1, 1);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
+
+ assert_node_ref_count (ref_model, &grandparent3, 2);
gtk_widget_destroy (tree_view);
g_object_unref (filter_model);
}
static void
-ref_count_transfer_child_level_insert (void)
+ref_count_transfer_root_level_remove_filtered (void)
{
- GtkTreeIter grandparent1;
- GtkTreeIter parent1, parent2, parent3;
- GtkTreeIter new_node;
+ GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
GtkTreeModel *model;
GtkTreeModelRefCount *ref_model;
GtkTreeModel *filter_model;
GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
model = gtk_tree_model_ref_count_new ();
ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
/* + grandparent1
- * + parent1
- * + parent2
- * + parent3
+ * + grandparent2
+ * + grandparent3
+ * + grandparent4
*/
gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
- gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
- gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
- gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
+
+ /* Filter first node */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
tree_view = gtk_tree_view_new_with_model (filter_model);
- assert_node_ref_count (ref_model, &grandparent1, 3);
- assert_node_ref_count (ref_model, &parent1, 1);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 2);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 2);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent4);
+
+ /* Check level length to get root level cached again */
+ check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 0);
+
+ assert_node_ref_count (ref_model, &grandparent1, 1);
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
+
+ assert_node_ref_count (ref_model, &grandparent1, 1);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 1);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+
+ check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 1);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_root_level_reordered (void)
+{
+ GtkTreeIter grandparent1, grandparent2, grandparent3;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ /* + grandparent1
+ * + grandparent2
+ * + grandparent3
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 2);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_after (GTK_TREE_STORE (model),
+ &grandparent1, &grandparent3);
+
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+ assert_node_ref_count (ref_model, &grandparent1, 1);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_root_level_reordered_filtered (void)
+{
+ GtkTreeIter grandparent1, grandparent2, grandparent3;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+ /* + grandparent1
+ * + grandparent2
+ * + grandparent3
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
+
+ /* Test with 1 node filtered */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+
+ /* Move the invisible node grandparent1 */
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_after (GTK_TREE_STORE (model),
+ &grandparent1, &grandparent3);
+
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+
+ /* Move the invisible node grandparent1 */
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_before (GTK_TREE_STORE (model),
+ &grandparent1, &grandparent2);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+
+ /* Now swap grandparent2 and grandparent3, first reference must transfer */
+ /* gtk_tree_store_swap() will emit rows-reordered */
+ gtk_tree_store_swap (GTK_TREE_STORE (model),
+ &grandparent2, &grandparent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 2);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+
+ /* Swap back */
+ gtk_tree_store_swap (GTK_TREE_STORE (model),
+ &grandparent2, &grandparent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 2);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+
+ /* Test with two nodes filtered */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 2);
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_before (GTK_TREE_STORE (model),
+ &grandparent3, &grandparent1);
+
+ assert_node_ref_count (ref_model, &grandparent3, 2);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_root_level_filter (void)
+{
+ GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
+ GtkTreeIter new_node;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+ /* + grandparent1
+ * + grandparent2
+ * + grandparent3
+ * + grandparent4
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
+
+ /* Filter first node */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 2);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 2);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 2);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
+
+ assert_node_ref_count (ref_model, &new_node, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 2);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &new_node, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
+ gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
+
+ assert_node_ref_count (ref_model, &new_node, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &new_node, 2);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_child_level_insert (void)
+{
+ GtkTreeIter grandparent1;
+ GtkTreeIter parent1, parent2, parent3;
+ GtkTreeIter new_node;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ /* + grandparent1
+ * + parent1
+ * + parent2
+ * + parent3
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
assert_node_ref_count (ref_model, &parent2, 0);
assert_node_ref_count (ref_model, &parent3, 0);
}
static void
-ref_count_transfer_child_level_reordered (void)
+ref_count_transfer_child_level_remove (void)
+{
+ GtkTreeIter grandparent1;
+ GtkTreeIter parent1, parent2, parent3;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ /* + grandparent1
+ * + parent1
+ * + parent2
+ * + parent3
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent3, 1);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_child_level_remove_filtered (void)
+{
+ GtkTreeIter grandparent1;
+ GtkTreeIter parent1, parent2, parent3, parent4;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+ /* + grandparent1
+ * + parent1
+ * + parent2
+ * + parent3
+ * + parent4
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent4, &grandparent1);
+
+ /* Filter first node */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent4, 0, TRUE, -1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+ assert_node_ref_count (ref_model, &parent4, 0);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent3, 1);
+ assert_node_ref_count (ref_model, &parent4, 0);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent4, 1);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent4);
+
+ /* Check level length to get level cached again */
+ check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 0);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+
+ check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 1);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_child_level_reordered (void)
+{
+ GtkTreeIter grandparent1;
+ GtkTreeIter parent1, parent2, parent3;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ /* + grandparent1
+ * + parent1
+ * + parent2
+ * + parent3
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_after (GTK_TREE_STORE (model),
+ &parent1, &parent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+ assert_node_ref_count (ref_model, &parent1, 0);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_child_level_reordered_filtered (void)
+{
+ GtkTreeIter grandparent1;
+ GtkTreeIter parent1, parent2, parent3;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+ /* + grandparent1
+ * + parent1
+ * + parent2
+ * + parent3
+ */
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+
+ /* Test with 1 node filtered (parent1) */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ /* Move invisible node parent 1 */
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_after (GTK_TREE_STORE (model),
+ &parent1, &parent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+ assert_node_ref_count (ref_model, &parent1, 0);
+
+ /* Move invisible node parent 1 */
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_before (GTK_TREE_STORE (model),
+ &parent1, &parent2);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ /* Now swap parent2 and parent2, first reference must transfer */
+ /* gtk_tree_store_swap() will emit rows-reordered */
+ gtk_tree_store_swap (GTK_TREE_STORE (model),
+ &parent2, &parent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent3, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+
+ /* Swap back */
+ gtk_tree_store_swap (GTK_TREE_STORE (model),
+ &parent2, &parent3);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent2, 1);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &parent1, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ /* Test with two nodes filtered */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent2, 0);
+ assert_node_ref_count (ref_model, &parent3, 1);
+
+ /* gtk_tree_store_move() will emit rows-reordered */
+ gtk_tree_store_move_before (GTK_TREE_STORE (model),
+ &parent3, &parent1);
+
+ assert_node_ref_count (ref_model, &parent3, 1);
+ assert_node_ref_count (ref_model, &parent2, 0);
+ assert_node_ref_count (ref_model, &parent1, 0);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_child_level_filter (void)
{
- GtkTreeIter grandparent1;
- GtkTreeIter parent1, parent2, parent3;
+ GtkTreeIter root;
+ GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
+ GtkTreeIter new_node;
GtkTreeModel *model;
GtkTreeModelRefCount *ref_model;
GtkTreeModel *filter_model;
GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
model = gtk_tree_model_ref_count_new ();
ref_model = GTK_TREE_MODEL_REF_COUNT (model);
- /* + grandparent1
- * + parent1
- * + parent2
- * + parent3
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+ /* + root
+ * + grandparent1
+ * + grandparent2
+ * + grandparent3
+ * + grandparent4
*/
- gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
- gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
- gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
- gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, &root);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, &root);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, &root);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, &root);
+
+ /* Filter first node */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &root, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
tree_view = gtk_tree_view_new_with_model (filter_model);
- assert_node_ref_count (ref_model, &grandparent1, 3);
- assert_node_ref_count (ref_model, &parent1, 1);
- assert_node_ref_count (ref_model, &parent2, 0);
- assert_node_ref_count (ref_model, &parent3, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
- /* gtk_tree_store_move() will emit rows-reordered */
- gtk_tree_store_move_after (GTK_TREE_STORE (model),
- &parent1, &parent3);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
- assert_node_ref_count (ref_model, &grandparent1, 3);
- assert_node_ref_count (ref_model, &parent2, 1);
- assert_node_ref_count (ref_model, &parent3, 0);
- assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 1);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 1);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
+
+ assert_node_ref_count (ref_model, &new_node, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 1);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &new_node, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
+ gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
+
+ assert_node_ref_count (ref_model, &new_node, 0);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 1);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
+
+ assert_node_ref_count (ref_model, &new_node, 1);
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 0);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
+
+ assert_node_ref_count (ref_model, &grandparent1, 0);
+ assert_node_ref_count (ref_model, &grandparent2, 1);
+ assert_node_ref_count (ref_model, &grandparent3, 0);
+ assert_node_ref_count (ref_model, &grandparent4, 0);
+
+ gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
gtk_widget_destroy (tree_view);
g_object_unref (filter_model);
set_path_visibility (&fixture, "0", FALSE);
/* check_filter_model (&fixture); */
signal_monitor_assert_is_empty (fixture.monitor);
+
+ g_object_unref (fixture.filter);
+ g_object_unref (fixture.store);
+ gtk_widget_destroy (tree_view);
}
set_path_visibility (&fixture, "0", FALSE);
/* check_filter_model (&fixture); */
signal_monitor_assert_is_empty (fixture.monitor);
+
+ g_object_unref (fixture.filter);
+ g_object_unref (fixture.store);
+ gtk_widget_destroy (tree_view);
}
static void
set_path_visibility (&fixture, "0", FALSE);
/* check_filter_model (&fixture); */
signal_monitor_assert_is_empty (fixture.monitor);
+
+ g_object_unref (fixture.filter);
+ g_object_unref (fixture.store);
+ gtk_widget_destroy (tree_view);
}
static gboolean
set_path_visibility (&fixture, "0", FALSE);
/* check_filter_model (&fixture); */
signal_monitor_assert_is_empty (fixture.monitor);
+
+ g_object_unref (fixture.filter);
+ g_object_unref (fixture.store);
+ gtk_widget_destroy (tree_view);
}
static void
specific_at_least_2_children_filter_on_sort_model (void)
{
+ GtkTreeRowReference *ref;
GtkTreeModel *filter;
GtkTreeModel *sort_model;
GtkTreeIter iter, root;
{
GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1);
- GtkTreeRowReference *ref;
ref = gtk_tree_row_reference_new (sort_model, path);
gtk_tree_path_free (path);
gtk_tree_store_append (fixture.store, &root, NULL);
check_level_length (fixture.filter, NULL, 1);
signal_monitor_assert_is_empty (fixture.monitor);
+
+ gtk_tree_row_reference_free (ref);
+ g_object_unref (fixture.filter);
+ g_object_unref (fixture.store);
+ gtk_widget_destroy (tree_view);
}
g_object_unref (filter);
}
+static void
+specific_bug_657353_related (void)
+{
+ GtkTreeIter node1, node2, node3, node4;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeModel *filter_model;
+ GtkWidget *tree_view;
+ GType column_types[] = { G_TYPE_BOOLEAN };
+
+ /* gtk_tree_model_filter_rows_reordered() used to have a problem to
+ * not properly transfer the first ref count when the first node in
+ * the level does not have elt->offset == 0. This test checks for
+ * that. This bug could cause the faulty condition
+ * elt->ext_ref_count > elt->ref_count
+ * to raise.
+ */
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
+ column_types);
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &node1, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &node2, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &node3, NULL);
+ gtk_tree_store_append (GTK_TREE_STORE (model), &node4, NULL);
+
+ /* Hide the first node */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &node1, 0, FALSE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &node2, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, TRUE, -1);
+ gtk_tree_store_set (GTK_TREE_STORE (model), &node4, 0, TRUE, -1);
+
+ filter_model = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ assert_node_ref_count (ref_model, &node1, 0);
+ assert_node_ref_count (ref_model, &node2, 2);
+ assert_node_ref_count (ref_model, &node3, 1);
+ assert_node_ref_count (ref_model, &node4, 1);
+
+ /* Swap nodes 2 and 3 */
+
+ /* gtk_tree_store_swap() will emit rows-reordered */
+ gtk_tree_store_swap (GTK_TREE_STORE (model),
+ &node2, &node3);
+
+ assert_node_ref_count (ref_model, &node1, 0);
+ assert_node_ref_count (ref_model, &node3, 2);
+ assert_node_ref_count (ref_model, &node2, 1);
+ assert_node_ref_count (ref_model, &node4, 1);
+
+ /* Hide node 3 */
+ gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, FALSE, -1);
+
+ assert_node_ref_count (ref_model, &node1, 0);
+ assert_node_ref_count (ref_model, &node3, 0);
+ assert_node_ref_count (ref_model, &node2, 2);
+ assert_node_ref_count (ref_model, &node4, 1);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static gboolean
+specific_bug_657353_visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gchar *str;
+ gboolean ret = FALSE;
+
+ gtk_tree_model_get (model, iter, 0, &str, -1);
+ ret = strstr (str, "hidden") ? FALSE : TRUE;
+ g_free (str);
+
+ return ret;
+}
+
+static void
+specific_bug_657353 (void)
+{
+ GtkListStore *store;
+ GtkTreeModel *sort_model;
+ GtkTreeModel *filter_model;
+ GtkTreeIter iter, iter_a, iter_b, iter_c;
+ GtkWidget *tree_view;
+
+ /* This is a very carefully crafted test case that is triggering the
+ * situation described in bug 657353.
+ *
+ * GtkListStore acts like EphyCompletionModel
+ * GtkTreeModelSort acts like the sort model added in
+ * ephy_location_entry_set_completion.
+ * GtkTreeModelFilter acts like the filter model in
+ * GtkEntryCompletion.
+ */
+
+ /* Set up a model that's wrapped in a GtkTreeModelSort. The first item
+ * will be hidden.
+ */
+ store = gtk_list_store_new (1, G_TYPE_STRING);
+ gtk_list_store_insert_with_values (store, &iter_b, 0, 0, "BBB hidden", -1);
+ gtk_list_store_insert_with_values (store, &iter, 1, 0, "EEE", -1);
+ gtk_list_store_insert_with_values (store, &iter, 2, 0, "DDD", -1);
+ gtk_list_store_insert_with_values (store, &iter_c, 3, 0, "CCC", -1);
+
+ sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
+
+ filter_model = gtk_tree_model_filter_new (sort_model, NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
+ specific_bug_657353_visible_func,
+ filter_model, NULL);
+
+ tree_view = gtk_tree_view_new_with_model (filter_model);
+
+ /* This triggers emission of rows-reordered. The elt with offset == 0
+ * is hidden, which used to cause misbehavior. (The first reference should
+ * have moved to CCC, which did not happen).
+ */
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
+ 0, GTK_SORT_ASCENDING);
+
+ /* By inserting another item that will appear at the first position, a
+ * reference transfer is done from CCC (which failed to get this reference
+ * earlier) to AAA. At this point, the rule
+ * elt->ref_count >= elt->ext_ref_count is broken for CCC.
+ */
+ gtk_list_store_insert_with_values (store, &iter_a, 6, 0, "AAA", -1);
+
+ /* When we hide CCC, the references cannot be correctly released, because
+ * CCC failed to get a reference during rows-reordered. The faulty condition
+ * only manifests itself here with MODEL_FILTER_DEBUG disabled (as is usual
+ * in production).
+ */
+ gtk_list_store_set (store, &iter_c, 0, "CCC hidden", -1);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (sort_model);
+ g_object_unref (store);
+}
+
+static void
+specific_bug_658696 (void)
+{
+ GtkTreeStore *store;
+ GtkTreeModel *filter;
+ GtkTreePath *vroot;
+ GtkTreeIter iter;
+
+ store = create_tree_store (4, TRUE);
+
+ vroot = gtk_tree_path_new_from_indices (0, 0, -1);
+ filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), vroot);
+ gtk_tree_path_free (vroot);
+
+ /* This used to cause a crash in gtk_tree_model_filter_check_ancestors() */
+ gtk_tree_store_append (store, &iter, NULL);
+
+ g_object_unref (store);
+ g_object_unref (filter);
+}
+
+static gboolean
+specific_bug_659022_visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GtkTreeIter tmp;
+
+ if (!gtk_tree_model_iter_parent (model, &tmp, iter))
+ {
+ if (gtk_tree_model_iter_n_children (model, iter) >= 2)
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+specific_bug_659022_row_changed_emission (void)
+{
+ GtkTreeModel *filter;
+ GtkTreeModel *model;
+ GtkTreeIter parent, child, child2;
+ GtkTreePath *path;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+
+ filter = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+ specific_bug_659022_visible_func,
+ NULL, NULL);
+
+ tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
+
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &parent, NULL, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child, &parent, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child2, &parent, 0);
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &child2);
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
+
+ path = gtk_tree_model_get_path (model, &child);
+ gtk_tree_model_row_changed (model, path, &child);
+ gtk_tree_path_free (path);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter);
+ g_object_unref (model);
+}
+
+static void
+specific_bug_659022_row_deleted_node_invisible (void)
+{
+ GtkTreeModel *filter;
+ GtkTreeModel *model;
+ GtkTreeIter parent, child;
+ GtkTreeIter parent2, child2, child3;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+
+ filter = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+ specific_bug_659022_visible_func,
+ NULL, NULL);
+
+ tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
+
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &parent, NULL, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child, &parent, 0);
+
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &parent2, NULL, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child2, &parent2, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child3, &parent2, 0);
+
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
+
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter);
+ g_object_unref (model);
+}
+
+static void
+specific_bug_659022_row_deleted_free_level (void)
+{
+ GtkTreeModel *filter;
+ GtkTreeModel *model;
+ GtkTreeModelRefCount *ref_model;
+ GtkTreeIter parent, child;
+ GtkTreeIter parent2, child2, child3;
+ GtkWidget *tree_view;
+
+ model = gtk_tree_model_ref_count_new ();
+ ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+
+ filter = gtk_tree_model_filter_new (model, NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
+ specific_bug_659022_visible_func,
+ NULL, NULL);
+
+ tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
+
+ /* Carefully construct a model */
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &parent, NULL, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child, &parent, 0);
+
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &parent2, NULL, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child2, &parent2, 0);
+ gtk_tree_store_insert (GTK_TREE_STORE (model), &child3, &parent2, 0);
+
+ /* Only parent2 is visible, child3 holds first ref count for that level
+ * (Note that above, both child2 as child3 are inserted at position 0).
+ */
+ assert_node_ref_count (ref_model, &parent, 0);
+ assert_node_ref_count (ref_model, &child, 0);
+ assert_node_ref_count (ref_model, &parent2, 3);
+ assert_node_ref_count (ref_model, &child3, 1);
+ assert_node_ref_count (ref_model, &child2, 0);
+
+ /* Make sure child level is cached */
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
+
+ assert_node_ref_count (ref_model, &parent, 0);
+ assert_node_ref_count (ref_model, &child, 0);
+ assert_node_ref_count (ref_model, &parent2, 3);
+ assert_node_ref_count (ref_model, &child3, 2);
+ assert_node_ref_count (ref_model, &child2, 1);
+
+ gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
+
+ assert_node_ref_count (ref_model, &parent, 0);
+ assert_node_ref_count (ref_model, &child, 0);
+ assert_node_ref_count (ref_model, &parent2, 3);
+ assert_node_ref_count (ref_model, &child3, 1);
+ assert_node_ref_count (ref_model, &child2, 0);
+
+ /* Remove node with longer child level first */
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
+ gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter);
+ g_object_unref (model);
+}
+
/* main */
void
ref_count_three_levels);
g_test_add_func ("/TreeModelFilter/ref-count/delete-row",
ref_count_delete_row);
+ g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1",
+ ref_count_filter_row_length_1);
+ g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-root-level",
+ ref_count_filter_row_length_1_remove_in_root_level);
+ g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-child-level",
+ ref_count_filter_row_length_1_remove_in_child_level);
+ g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1",
+ ref_count_filter_row_length_gt_1);
+ g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1-visible-children",
+ ref_count_filter_row_length_gt_1_visible_children);
g_test_add_func ("/TreeModelFilter/ref-count/cleanup",
ref_count_cleanup);
g_test_add_func ("/TreeModelFilter/ref-count/row-ref",
*/
g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/insert",
ref_count_transfer_root_level_insert);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove",
+ ref_count_transfer_root_level_remove);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove/filtered",
+ ref_count_transfer_root_level_remove_filtered);
g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered",
ref_count_transfer_root_level_reordered);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered/filtered",
+ ref_count_transfer_root_level_reordered_filtered);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/filter",
+ ref_count_transfer_root_level_filter);
g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/insert",
ref_count_transfer_child_level_insert);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove",
+ ref_count_transfer_child_level_remove);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove/filtered",
+ ref_count_transfer_child_level_remove_filtered);
g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered",
ref_count_transfer_child_level_reordered);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered/filtered",
+ ref_count_transfer_child_level_reordered_filtered);
+ g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/filter",
+ ref_count_transfer_child_level_filter);
g_test_add_func ("/TreeModelFilter/specific/path-dependent-filter",
specific_path_dependent_filter);
specific_bug_549287);
g_test_add_func ("/TreeModelFilter/specific/bug-621076",
specific_bug_621076);
+ g_test_add_func ("/TreeModelFilter/specific/bug-657353-related",
+ specific_bug_657353_related);
+ g_test_add_func ("/TreeModelFilter/specific/bug-657353",
+ specific_bug_657353);
+ g_test_add_func ("/TreeModelFilter/specific/bug-658696",
+ specific_bug_658696);
+ g_test_add_func ("/TreeModelFilter/specific/bug-659022/row-changed-emission",
+ specific_bug_659022_row_changed_emission);
+ g_test_add_func ("/TreeModelFilter/specific/bug-659022/row-deleted-node-invisible",
+ specific_bug_659022_row_deleted_node_invisible);
+ g_test_add_func ("/TreeModelFilter/specific/bug-659022/row-deleted-free-level",
+ specific_bug_659022_row_deleted_free_level);
}