Tuesday, December 8, 2009

Quidgets: Fun and Easy Widgets

Quidgets (Quickly + Widgets) is a new project that I started be a container for all of the Python modules that I use over and over again in different forms throughout the projects that I work on. Essentially, I got tired of copying the modules into different projects, and I just couldn't find a proper upstream.

I plan to get Quidgets packaged and then into Universe so that I can simply set dependencies on Quidgets in projects like Bughugger. Also, if it's a unified project, I can accept other people's modules and have better collaboration on my modules.

One key thing about Quidgets, is that I want to keep all of the modules in it to follow the spirit of Quickly. Programming with Quickly modules should make Python programming, especially pygtk programming, more Easy and Fun. Since I am the only target user right now, it's easy to tell if my user base thinks it is easy and fun to program with Quickly modules.

Easy and Fun Threading
The first module that I added to Quidgets is my AsynchTaskProgressBox that I wrote over a year ago. This thing needs a better name. But in any case, since I wrote it, I haven't written any Ptyhon threading code, because this widget takes care of it for me.

I use AsynchTaskProgressBox to keep the UI from freezing while a program is doing long running task, like fetching something from the web. In order to write a threaded function I:
  1. write a function that I want to run on a thread
  2. instantiate an AsyncTaskProgressBox widget and hand the function to it, along with any parameters the function might need
  3. call "start()"

Trust me, this is waaaay easier than writing Python thread code yourself. Note also that I've created a way that you can sort of cancel a thread while it is running, and you get a free "Cancel" button, which you can hide if you want.

Here is a code sample from Bughugger:

from quidgets.widgets.asynch_task_progressbox import AsynchTaskProgressBox

def bugs_from_url(self, widget, data):
#the name of the search to use for the document tab and the url
#are passed in as data to this handler
name, url = data

#contruct a dictionary for passign this data into the AsynchTaskProgressBox
params = {"url":url, "name":name}

#create the progress box. __get_bugs_from_url is a function that retrieves
#bugs from a web server. It will get the params dictionary when it is run.
get_bugs_progressbox = AsynchTaskProgressBox(self.__get_bugs_from_url, params)

#add the progress box to the window. "progress_box" is the name of
#an HBox that I want to contain the AysnchTaskProgressBox
self.builder.get_object("progress_box").pack_end(get_bugs_progressbox, False, False)

#when the task is complete, I want it to call __get_bugs_complete
#whatever is returned from __get_bugs_from_url will be passed to
#__get_bugs_complete along with a reference to the AsynchProgressBox
#which is handy if you want to remove or hide it

#I want it to display, but this is optional

#Finally call start to kick of the thread
#the string is displayed in the progress box as it runs
get_bugs_progressbox.start("Retrieving team assigned bugs from Launchpad")

Here it is working:

So what is going on is that the ProgressBox is throbbing while the bugs are getting dowlnoaded from the server. The window UI does not block while that work is going on in the background. Again, there was NO THREAD code to write.

There's also sample code a the end of the code file in the trunk branch:

DictionaryGrid and the related GridFilter are also in there, will post on those later ....


  1. Thank you for saving us from Python threading! If someone else's threading code is solid and hidden, it could sometimes be a pleasure to use. Although it would be nice if the launchpad client library were asynchronous itself.

  2. Awesome! I just started using quickly and creating my first gtk apps. I popped in to #quickly to ask about some of this very functionality. The only thing I'd like to add to the threading would be a way to call back with a percentage for an actual progress bar rather than a busy indicator.