* 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);
}
g_object_unref (ref_model);
}
+static void
+ref_count_transfer_root_level_remove (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_remove (GTK_TREE_STORE (model), &grandparent1);
+
+ assert_node_ref_count (ref_model, &grandparent2, 2);
+ assert_node_ref_count (ref_model, &grandparent3, 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);
+ g_object_unref (ref_model);
+}
+
+static void
+ref_count_transfer_root_level_remove_filtered (void)
+{
+ 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
+ * + 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_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)
{
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)
{
GtkTreeModel *filter_model;
GtkWidget *tree_view;
- model = gtk_tree_model_ref_count_new ();
- ref_model = GTK_TREE_MODEL_REF_COUNT (model);
+ 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_prepend (GTK_TREE_STORE (model), &new_node, &grandparent1);
+
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &new_node, 1);
+ assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent2, 0);
+ assert_node_ref_count (ref_model, &parent3, 0);
+
+ gtk_widget_destroy (tree_view);
+ g_object_unref (filter_model);
+ g_object_unref (ref_model);
+}
+
+static 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);
- /* + grandparent1
- * + parent1
- * + parent2
- * + parent3
- */
+ assert_node_ref_count (ref_model, &grandparent1, 3);
+ assert_node_ref_count (ref_model, &parent1, 1);
- 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_prepend (GTK_TREE_STORE (model), &new_node, &grandparent1);
+ 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, &new_node, 1);
- assert_node_ref_count (ref_model, &parent1, 0);
+ assert_node_ref_count (ref_model, &parent1, 1);
assert_node_ref_count (ref_model, &parent2, 0);
- assert_node_ref_count (ref_model, &parent3, 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_filter (void)
+{
+ 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);
+
+ 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), &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, 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, 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);
+ g_object_unref (ref_model);
+}
+
+
static gboolean
specific_path_dependent_filter_func (GtkTreeModel *model,
GtkTreeIter *iter,
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 (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)
{
/* 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 */
*/
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_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);
}