Friday, December 18, 2009

Quidget Custom Filters Simplified

Last night I created a custom filter for bughugger. I knew when I created GridFilter that I would be able to easily create new filters, and when I added "filter_hints" I knew it would then be easy to add new custom filters for a grid.

But when I wrote the custom filter:
class StartsWithNumberFilterCombo(gtk.ComboBox):
def __init__(self):

combo_store = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_PYOBJECT)
combo_store.append(["=",lambda x,y: convert_to_num(x) == float(y) ])
combo_store.append(["<",lambda x,y: convert_to_num(x) < float(y) ])
combo_store.append([">",lambda x,y: convert_to_num(x) > float(y) ])
combo_store.append(["<=",lambda x,y: convert_to_num(x) <= float(y) ])
combo_store.append([">=",lambda x,y: convert_to_num(x) >= float(y) ])
gtk.ComboBox.__init__( self, combo_store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)

def convert_to_num(string):
return float(string.split(" ")[0])

I didn't like that I had to use my knowledge of the implementation details. In other words, it seemed easy to me because I know what a ListStore is, and I knew that a ComboBox uses a ListStore and that in this particular case the second field of the ListStore stores a reference to a function, while the first field stores a string to display in the combo.

So today I reworked the filters so that developers could easily write new filters without having to have knowledge of the implementation details. I create a new base class called "BlankFilterCombo" that has no associated filters by default. There is a single public member exposed, "append". Append takes text to display, and a filter to use for a filter.

So, now I could rewrite the custom filter code without sub-classing, and without understanding anything about how the filters are implemented:
  sw_filter = BlankFilterCombo()
sw_filter.append("=",lambda x,y: convert_to_num(x) == float(y) )
sw_filter.append("<",lambda x,y: convert_to_num(x) < float(y) )
sw_filter.append(">",lambda x,y: convert_to_num(x) > float(y) )
sw_filter.append("<=",lambda x,y: convert_to_num(x) <= float(y) )
sw_filter.append(">=",lambda x,y: convert_to_num(x) >= float(y) )

So now the code just appends the pairs of text and functions.

While I was at it, I did change the existing filters to sub-class BlankFilterCombo, but this is not visible to other developers.

About Quidgets
Quickly + Widgets = Quidgets
There is a Launchpad Project for Quidgets
The most up to date changes are in the Quidgets Trunk Branch
You can install Quidgets from the my PPA

1 comment: