Search code examples
perltreeviewgtkgtk2

TreeModelFilter in GTK/Perl - Question about set_visible_func


I am trying to filter a liststore using the GTK2::TreeModelFilter. I can't seem to find an example online that uses perl and I am getting syntax errors. Can someone help me with the syntax below? The $unfiltered_store is a liststore.

$filtered_store = Gtk2::TreeModeFilter->new($unfiltered_store);
$filtered_store->set_visible_func(get_end_products, $unfiltered_store);
$combobox = Gtk2::ComboBoxEntry->new($filtered_store,1);

Then somewhere below:

 sub get_end_products {
      my ($a, $b) = @_;

      warn(Dumper(\$a));
      warn(Dumper(\$b));
      return true;     # Return all rows for now
 }

Ultimately what I want to do is look at column 14 of the listore ($unfiltered_store) and if it is a certain value, then it filtered into the $filtered_store.

Can someone help me with the syntax on this? I checked a bunch of sites, but they're in other languages and using different syntax (like 'new_filter' -- doesn't exist with Perl GTK). This is the most elegant solution to a fix I need to make and I would prefer to learn how to use this rather than using a brute force method of pulling and saving the filtered data.


Solution

  • The set_visible_func method of the filtered store should get a sub reference as the first argument, but you are not passing a sub reference here:

    $filtered_store->set_visible_func(get_end_products, $unfiltered_store);
    

    This will instead call the sub routine get_end_products and then pass on its return value (which is not a sub reference). To fix it add the reference operator \& in front of the sub name:

    $filtered_store->set_visible_func(\&get_end_products, $unfiltered_store);
    

    Regarding your other question in the comments: According to the documentation the user data parameter is passed as the third parameter to get_end_products, so you should define it like this:

    sub get_end_products {
          my ($model, $iter, $user_data) = @_;
          # Do something with $user_data
          return TRUE;
     }
    

    If for some reason $unfiltered_store is not passed on to get_end_products, you can try pass it using an anonymous sub instead, like this:

    $filtered_store->set_visible_func(
        sub { get_end_products( $unfiltered_store) });