Saturday, September 11, 2010

Anything New in Quickly Widgets for Maverick?

Going into Maverick, I had envisioned myself spending a lot of free time on Quickly Widgets throughout the cycle. Sadly, though, due to various factors, I did not make the kind of progress I was hoping to. Then a couple of days ago didrocks pinged me to ask if I was going to update Quickly Widgets for Maverick, because if I was, now is the time. So, today I went through all my changes over the last few months, to make sure tests were passing, and that they were generally working well.

Well, it was a good exercise, because I came to find that I had actually made some decent progress! Here's a quick overview of what is new and improved in Quickly Widgets for Maverick (or will be when it actually gets into Maverick next week). Note that most of the changes were put into place for specific users, so I know that each of these improvements will be useful to at least one person :)

Enhanced DictionaryGrid
In Lucid, when you created a dictionary grid, the keys were used for the titles of the columns. I think this is good, because it's easy and fun. You can get going fast, and a fair amount of the time, this functionality will be more than sufficient. However, sometimes that column title needs to be changed or maybe different than the keys. This was doable, of course, because a DictionaryGrid is just a TreeView, and you can set the titles on a TreeView. You could loop through the columns, and set the titles as desired. Too much code, so I added a helper function. You can create a dictionary of keys to titles, and set them. So an app like PyTask would do this if it wanted different keys and titles:
        titles = {"name":_("Name"),"priority":_("Priority"),

You don't have to do all of the titles, you can just pass in the keys that you want you to change titles for. I also made it a bit easier to access a column. You can just index into the columns by the key. So in the tests, for example, you can see where I used it like this:

Nice one liner. This is just accessing the gtk.TreeViewColumn, so you can whatever you need to with the column, this just makes it easy to get to the columns you need.

As I previously blogged, there is now a datecolumn with built in editing (thanks to the pygtk faq):

And there is a grid filter to go with it:

So now, any column with a key that ends in "date" will default to be a date column.

DictionaryGrid also has an enriched set of arguments for the cell-edited signal. In addition to the row index and key that were previously reported, it now tells you the new value and also provides the dictionary for the row as well. Makes it easier to decide what to do when a cell is edited without having to probe into the grid.

Enhancemed CouchGrid
The most salient enhancement to CouchGrid, is that it's easy to tell the grid to delete data form desktopcouch now. You do this by passing delete=True to the remove_selected_rows function. So apps like PyTask don't have to do all these crazy contortions to remove data from the underlying store, PyTask just does this:
    def remove_row(self, widget, data=None):
"""Removes the currently selected row from the couchgrid."""


I like this because it lets the programmer keep the grid as their mental model of how to interact with the underlying store, and keeping desktopcouch an incidental piece of plumbing.

Enhanced GridFilters
Personally, the ability to apply a filter UI to a grid with just a few lines of code is one of the things about quidgets of which I am the most proud. I still don't know how I managed to pull it off, but I did. I like it because it turns a big chore into something easy and fun. If nothing else, it makes a sweet demo.

So I did make some good progress with this in Maverick. The key thing was that I refactored what a FilterRow contains. The FilterRows were hard coded to use a combo box and TextEntry. This became limiting with data types other than strings. So, I did some open heart surgery on the Filter Code, and after a successful refactoring, can now drop in any set of widgets I would like for a filter row. In addition to a date filter, there's an IntegerFilter now:

New Widgets
Thanks to sil, it's now really trivial to download content from the Internet. Sil wrote the code, and I did a vblog about this a while back. In case you missed that:
This widget works by reusing the common signal handling patterns in PyGtk. From the test app:
    def start_download(self, btn):
prog = UrlFetchProgressBox("")
prog.connect("downloaded", self.downloaded)
self.vbox.pack_start(prog, expand=False)

def downloaded(self, widget, content):
print "downloaded %s bytes of content" % len(content)

There is also a TextEditor now. This removes all the bookkeeping code that you have to write to keep a TextView, TextBuffer, Markers, etc... all straight.

For example, to tell the TextEditor to highlight a word, just add it to the text editor's list of words to highlight:

Really! That's all you need to highlight the word "some" in a text editor.
It's also got undo and redo built in! So instead of mucking with this yourself, you can hook up an undo command with a one-liner:
        undo_button = gtk.Button("Undo")

If you haven't tried making an undo, redo stack yourself, trust me, this is much easier.

I recently blogged about the new WebCamBox as well. I won't rehash that here.

House Keeping
Finally, I went through this morning to ensure that all of the quidgets were using gettext properly (so bring on the translations if you got 'em), and I've also been adding and improving tests as I've been along.

I guess I should write a nice comprehensive tutorial or similar. But in the meantime, there are lots of videos and such on my blog. So, if you want to write an app for Ubuntu, consider using Quickly and Quickly Widgets, because it's getting more fun and more easy with each release!

About Quickly Widgets
Quickly + Widgets = Quidgets
There is a Launchpad Project for Quickly Widgets
The most up to date changes are in the Quickly Widgets Trunk Branch


  1. Nice work with quidgets.

    I've been wondering though if there's plans to include these widgets inside Glade itself so that you could just drag and drop them into place?

    Right now we need to add the widgets ourselves but as the number of widgets increase, we might have problems with users not knowing what's available. The amount of manual coding required would also increase which kinda defeats the purpose of Quickly, no?

  2. @kahping - You are so right. Glade integration is something I really want to get to. I think for Glade, it's really just a matter of crafting an XML catalog file. But I suspect it will take some work the get each quidget working properly within glade. Making sure the properties work correctly, and possibly adding some special editing UI.