Wednesday, December 16, 2009

Conventions for DictionaryGrid and Quidgets (or more on why I hate TreeViews)

We ran into a rather sorry limitation with the current implementation of the DictionaryGrid Quidget. Well, really, I blame the TreeView API, and it's complexity and rigidness.

It turns out that if a TreeView is treating a column as a string, and those strings are numbers, than the ordering can get a little screwy if you sort columns. Basically, the ordering of strings is not numeric, so the different number of characters can through it off. For example, in this test app, you can see that the column for key2 is in an odd order:
Clearly 55 is not the least of these numbers.

As a result, I worked a bit with the DictionaryGrid code, and realized that I can in fact set the proper type for column at run time, and don't have to treat them all as string. (Thanks to Robert Ancell ;) )

So the updated code for DictionaryGrid can set the proper column type in two ways, by convention of by configuration. The supported way to configure is to pass in "type_hints" when you create the Grid. This is a dictionary of keys to gobject types. So the following code will make thekey2 column properly sortable:
 dicts = [{"ID": 0, "key2": 55, "tags": "aaa bbb ccc","_foo":"bar"},
{"ID": 1, "key2": 6, "tags": "bbb ccc ddd","_foo":"bar"},
{"ID": 2, "key2": 7, "tags": "ccc ddd eee","_foo":"bar"},
{"ID": 3, "key2": 8, "tags": "ddd eee fff","_foo":"bar"},
{"ID": 4, "key2": 9, "tags": "eee fff ggg","_foo":"bar"}]

keys = ["ID","key2","tags"]
type_hints = {"key2":gobject.TYPE_INT}
grid = DictionaryGrid(dicts, keys,type_hints)

These changes are in trunk, but as there are no tests yet, they have not been pushed to my PPA.

Note that with typing of columns, it's no longer a simple matter of converting everything to a string, so I will need to add some code to check the column's type and then convert the values to the appropriate to type to ensure that the code is suitably robust.

Now, it's nice that you can configure in this manner, but I am a big fan of the Ruby on Rails principle of Conventions over Configuration. So, I've already added one convention. Any column who's key is "id" (or "Id", "ID", "iD") will automatically be set to a column with type Integer.

I want to add a nice rich list of conventions to make using a DictionaryGrid super easy and fun. For example:
  • ends in " count" = Integer type
  • ends in "?" = Boolean type (column will have check boxes)
  • is "cost" or "price" = Float type, and value is properly formatted
  • ends in "%" = Float type
  • etc...
Everything else will default to String. In addition to typing the column properly, these same conventions will cause the proper GridFilter type to be used by default.

The use of these conventions should reduce the need for the use of type_hints, though won't be intended to eliminate them. The configuration options should be available for developers who want or need that option. Though by default, if a type_hint is provided for a column, it would be good if the related filter type were picked up as well.

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: