Here is my problem.
I have TreeStore with data, that looks like this:

"item 0 - level 0"
        "item 0:0 - level 1"
                "item 0:0:0 - level 2"
                "item 0:0:1 - level2"
"item 1 - level 0"
        "item 1:0 - level 1"
                "item 1:0:0 - level 2"

...and so on. Depth of this tree is exactly 3.

Now I want to filter the lowest level items. Only 2nd level items, which names 
contain some substring will be visible. 0th and 1st level items will be 
visible only, when they contain some visible 2nd level items. That means: 
if "item 0:0:0" and "item 0:0:1" will be filtered out, "item 0" and "item 
0:0" should disappear as well.

The process of filtering has been solved and is not a problem here. There are 
two implementations (attached to this post): one in C, the other one in 
Python. In fact they both are supposed to work in identical way. One was 
derived from another by simply translating statements.

The problem is that while C version works as expected (hides level 0 and 1 
rows when necessary while showing level 2 rows), the Python version gives 
unpredictable results. It looks like it filters rows properly (level 0 items 
disappear when they should), but never shows level 1 and 2 items!

From these two examples it looks to me like there is some problem on Python-C 
boundary. I'm not familiar with that kind of debugging, so I ask you for 
help. Does anybody know what's the source of the problem can be? Can anybody 
either give me hints on ways of debugging such problems or take a look and 
provide exact solution?

Thank you in advance,
p_michalczyk
#include <gtk/gtk.h>
#include <iostream>
#include <set>
#include <string>
#include <assert.h>
using namespace std;

enum
{
    COL_NAME = 0,
    COL_LEVEL = 1,
    COL_ID = 2,
    NUM_COLS
};

typedef struct {
    char name[50];
    uint level;
    uint id;
} row;

row rows[] = {{"albums", 0, 501}, {"richard_galliano", 1, 502}, {"richard_galliano_luz_negra", 2, 503},
    {"classical", 0, 504}, {"collections", 1, 505}, {"magic_of_waltz_cd1", 2, 506},
    {"magic_of_waltz_cd2", 2, 507}};

GtkTreeModelFilter *modelFilter;
set<int> visibleItems;
string filterText;
GtkWidget *view;

void
onEntryChanged(GtkWidget *entry, void *data) {
    cout << gtk_entry_get_text(GTK_ENTRY(entry)) << endl;
    filterText = gtk_entry_get_text(GTK_ENTRY(entry));
    visibleItems.clear();
    gtk_tree_model_filter_refilter(modelFilter);
    gtk_tree_view_expand_all(GTK_TREE_VIEW (view));
    //cout.flush();
}

gboolean visibleFunc(GtkTreeModel *model, GtkTreeIter *iter, gpointer data) {
    gint level, id;
    gtk_tree_model_get(model, iter, 1, &level, 2, &id, -1);

    if( level == 0) {
        return visibleItems.find(id) != visibleItems.end();
    }
    else if( level == 1) {
        return visibleItems.find(id) != visibleItems.end();
    }
    else if( level == 2) {
        gchar* text;
        gtk_tree_model_get(model, iter, 0, &text, -1);
        string albumName = text;
        
        if( !filterText.empty() && (albumName.find(filterText) == -1)) {
            return 0;
        }
        else {
            gboolean ret;
            GtkTreeIter artistIter, reposIter;
            ret = gtk_tree_model_iter_parent(model, &artistIter, iter);
            assert(ret);
            ret = gtk_tree_model_iter_parent(model, &reposIter, &artistIter);
            assert(ret);

            gint reposId;
            gtk_tree_model_get(model, &reposIter, 2, &reposId, -1);
            if( visibleItems.find(reposId) == visibleItems.end()) {
                visibleItems.insert(reposId);
                GtkTreePath* path;
                path = gtk_tree_model_get_path(model, &reposIter);
                gtk_tree_model_row_changed(model, path, &reposIter);
                gtk_tree_path_free(path);
            }

            gint artistId;
            gtk_tree_model_get(model, &artistIter, 2, &artistId, -1);
            if( visibleItems.find(artistId) == visibleItems.end()) {
                visibleItems.insert(artistId);
                GtkTreePath* path;
                path = gtk_tree_model_get_path(model, &artistIter);
                gtk_tree_model_row_changed(model, path, &artistIter);
                gtk_tree_path_free(path);
            }

            return 1;
        }
    }

    return 0;
}

int
main (int argc, char *argv[])
{
    GtkWidget *window;
    GtkCellRenderer     *renderer;
    GtkTreeModel        *model;

    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_resize(GTK_WINDOW(window), 300, 250);
    g_signal_connect (window, "delete_event", gtk_main_quit, NULL);

    view = gtk_tree_view_new ();

    renderer = gtk_cell_renderer_text_new ();
    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view),
                                                -1,
                                                "Name",
                                                renderer,
                                                "text", COL_NAME,
                                                NULL);

    GtkTreeStore  *store;
    GtkTreeIter    iter[5];

    store = gtk_tree_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT);

    uint i;
    for(i = 0; i < sizeof(rows)/sizeof(rows[0]); i++) {
        if(rows[i].level == 0)
            gtk_tree_store_append (store, &iter[rows[i].level], NULL);
        else
            gtk_tree_store_append (store, &iter[rows[i].level], &iter[rows[i].level-1]);
        
        gtk_tree_store_set (store, &iter[rows[i].level],
                        COL_NAME, rows[i].name,
                        COL_LEVEL, rows[i].level,
                        COL_ID, rows[i].id,
                        -1);
    }

    model = GTK_TREE_MODEL (store);

    modelFilter = GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new(model, NULL));
    gtk_tree_model_filter_set_visible_func(modelFilter, visibleFunc, NULL, NULL);
    gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL(modelFilter));
    
    GtkWidget *box = gtk_vbox_new(FALSE, 5);
    GtkWidget *entry = gtk_entry_new();
    
    gtk_box_pack_start(GTK_BOX(box), entry, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(box), view, TRUE, TRUE, 0);

    gtk_container_add (GTK_CONTAINER (window), box);
    
    g_signal_connect(entry, "changed", (GCallback)onEntryChanged, NULL);
    
    gtk_tree_model_filter_refilter(modelFilter);
    gtk_tree_view_expand_all(GTK_TREE_VIEW (view));
    gtk_widget_show_all (window);
    gtk_main ();
    
    g_object_unref (modelFilter);

    return 0;
}

Attachment: tmf.py
Description: application/python

_______________________________________________
pygtk mailing list   [email protected]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to