I have two Gtk.Comboboxes
on a main window :
Gtk.Liststore
Gtk.TreeModelFilter
which is linked to a second Gtk.Liststore
When I select a value in the first one, the second one displays values according to my selection. This works well in the main window.
But in my application, I need to use this comboboxes combination many times, and when I use it on another window, this generates a Gtk Error that I don't understand:
"Gtk-CRITICAL **: 00:27:38.289: gtk_tree_model_filter_set_visible_func: assertion 'filter->priv->visible_method_set == FALSE' failed"
Could someone explain me what's wrong with my code and what is the meaning of that error message?
Here is the glade file (test.ui)
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name name -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">1</col>
<col id="1" translatable="yes">fruits</col>
</row>
<row>
<col id="0" translatable="yes">2</col>
<col id="1" translatable="yes">colors</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore2">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name name -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">10</col>
<col id="1" translatable="yes">lemon</col>
</row>
<row>
<col id="0" translatable="yes">11</col>
<col id="1" translatable="yes">apple</col>
</row>
<row>
<col id="0" translatable="yes">12</col>
<col id="1" translatable="yes">strawberry</col>
</row>
<row>
<col id="0" translatable="yes">20</col>
<col id="1" translatable="yes">blue</col>
</row>
<row>
<col id="0" translatable="yes">21</col>
<col id="1" translatable="yes">yellow</col>
</row>
<row>
<col id="0" translatable="yes">22</col>
<col id="1" translatable="yes">purple</col>
</row>
</data>
</object>
<object class="GtkTreeModelFilter" id="filter">
<property name="child_model">liststore2</property>
</object>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<signal name="destroy" handler="on_quit" swapped="no"/>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">20</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Open other</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_other" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">20</property>
<property name="margin_right">20</property>
<property name="row_spacing">5</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkComboBox" id="w1_combo1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">liststore1</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="w1_combo2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">filter</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo1</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo2</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkDialog" id="window2">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<property name="transient_for">window1</property>
<child>
<placeholder/>
</child>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="btn_close">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin_left">20</property>
<property name="margin_right">20</property>
<property name="margin_top">20</property>
<property name="margin_bottom">20</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin_top">20</property>
<property name="margin_bottom">20</property>
<property name="vexpand">True</property>
<property name="row_spacing">5</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkComboBox" id="w2_combo1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">liststore1</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="w2_combo2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">filter</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo1</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo2</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-7">btn_close</action-widget>
</action-widgets>
</object>
</interface>
and the python file (test.py):
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import sys
class Main:
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file('test.ui')
self.builder.connect_signals(self)
self.obj = self.builder.get_object
self.window = self.obj('window1')
self.combo1 = self.obj('w1_combo1')
self.combo2 = self.obj('w1_combo2')
self.combo1.connect('changed', self.on_select, self.combo2)
self.filter = self.obj('filter')
self.filter.set_visible_func(self.filter_func)
self.combo1_val = None
self.window.show()
def on_other(self, btn):
Other(self.obj)
def on_select(self, combo, next_combo):
self.combo1_val = combo.get_active_id()
self.filter.refilter()
next_combo.set_active(0)
def filter_func(self, model, iter, data):
if self.combo1_val is None: return True
else: return self.combo1_val == model[iter][0][:1]
def on_quit(self, widget):
Gtk.main_quit()
class Other:
def __init__(self, obj):
self.obj = obj
self.window = self.obj('window2')
self.combo1 = self.obj('w2_combo1')
self.combo2 = self.obj('w2_combo2')
self.combo1.connect('changed', self.on_select, self.combo2)
self.filter = self.obj('filter')
self.filter.set_visible_func(self.filter_func)
self.btn_close = self.obj('btn_close')
self.btn_close.connect('clicked', self.on_hide)
self.combo1_val = None
self.window.show()
def on_select(self, combo, next_combo):
self.combo1_val = combo.get_active_id()
self.filter.refilter()
next_combo.set_active(0)
def filter_func(self, model, iter, data):
if self.combo1_val is None: return True
else: return self.combo1_val == model[iter][0][:1]
self.window.show()
def on_hide(self, btn):
self.window.hide()
def main():
app = Main()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
Thank you in advance.
The problem was due to the fact that the second combobox on the main window and the second combobox on 'other' window were using the same filter. I've created another filter and the second comboboxes have now their own filter linked to a common Gtk.Liststore.
Everything works fine, now.
Here are the corrected files :
The glade one :
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name name -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">1</col>
<col id="1" translatable="yes">fruits</col>
</row>
<row>
<col id="0" translatable="yes">2</col>
<col id="1" translatable="yes">colors</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore2">
<columns>
<!-- column-name id -->
<column type="gchararray"/>
<!-- column-name name -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">10</col>
<col id="1" translatable="yes">lemon</col>
</row>
<row>
<col id="0" translatable="yes">11</col>
<col id="1" translatable="yes">apple</col>
</row>
<row>
<col id="0" translatable="yes">12</col>
<col id="1" translatable="yes">strawberry</col>
</row>
<row>
<col id="0" translatable="yes">20</col>
<col id="1" translatable="yes">blue</col>
</row>
<row>
<col id="0" translatable="yes">21</col>
<col id="1" translatable="yes">yellow</col>
</row>
<row>
<col id="0" translatable="yes">22</col>
<col id="1" translatable="yes">purple</col>
</row>
</data>
</object>
<object class="GtkTreeModelFilter" id="w1_filter">
<property name="child_model">liststore2</property>
</object>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<signal name="destroy" handler="on_quit" swapped="no"/>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">20</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Open other</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_other" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">20</property>
<property name="margin_right">20</property>
<property name="row_spacing">5</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkComboBox" id="w1_combo1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">liststore1</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="w1_combo2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">w1_filter</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo1</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo2</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkTreeModelFilter" id="w2_filter">
<property name="child_model">liststore2</property>
</object>
<object class="GtkDialog" id="window2">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<property name="transient_for">window1</property>
<child>
<placeholder/>
</child>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="btn_close">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin_left">20</property>
<property name="margin_right">20</property>
<property name="margin_top">20</property>
<property name="margin_bottom">20</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="margin_top">20</property>
<property name="margin_bottom">20</property>
<property name="vexpand">True</property>
<property name="row_spacing">5</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkComboBox" id="w2_combo1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">liststore1</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="w2_combo2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="model">w2_filter</property>
<property name="active">0</property>
<property name="id_column">0</property>
<property name="active_id">0</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo1</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Combo2</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-7">btn_close</action-widget>
</action-widgets>
</object>
</interface>
And the python one :
#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import sys
class Main:
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file('test.ui')
self.builder.connect_signals(self)
self.obj = self.builder.get_object
self.window = self.obj('window1')
self.combo1 = self.obj('w1_combo1')
self.combo2 = self.obj('w1_combo2')
self.combo1.connect('changed', self.on_select, self.combo2)
self.filter = self.obj('w1_filter')
self.filter.set_visible_func(self.filter_func)
self.combo1_val = None
self.window.show()
def on_other(self, btn):
Other(self.obj)
def on_select(self, combo, next_combo):
self.combo1_val = combo.get_active_id()
self.filter.refilter()
next_combo.set_active(0)
def filter_func(self, model, iter, data):
#print(self.combo1_val, model[iter][0][:1])
if self.combo1_val is None: return True
else: return self.combo1_val == model[iter][0][:1]
def on_quit(self, widget):
Gtk.main_quit()
class Other:
def __init__(self, obj):
self.obj = obj
self.window = self.obj('window2')
self.combo1 = self.obj('w2_combo1')
self.combo2 = self.obj('w2_combo2')
self.combo1.connect('changed', self.on_select, self.combo2)
self.filter = self.obj('w2_filter')
self.filter.set_visible_func(self.filter_func)
self.btn_close = self.obj('btn_close')
self.btn_close.connect('clicked', self.on_hide)
self.combo1_val = None
self.window.show()
def on_select(self, combo, next_combo):
self.combo1_val = combo.get_active_id()
self.filter.refilter()
next_combo.set_active(0)
def filter_func(self, model, iter, data):
#print(self.combo1_val, model[iter][0][:1])
if self.combo1_val is None: return True
else: return self.combo1_val == model[iter][0][:1]
self.window.show()
def on_hide(self, btn):
self.window.hide()
def main():
app = Main()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())