Keyword appaweek

Today's fun task was the creation of a little prototype code to format the tag cloud for the drop handler project. I did it in the context of this blog, and so first I had to get my keywords functional. I already had a database column for them, but it turned out my updater wasn't writing them to the database. So that was easy.

Once I had keywords attached to my blog posts, I turned my attention to formatting them into keyword directories (the primary motivation for this was to make it possible to enable Technorati tagging, on which more later.) And then once that was done, I had all my keywords in a hash, so it occurred to me that I was most of the way towards implementing a tag cloud formatter anyway.

Here's the Perl I wrote just to do the formatting. It's actually amazingly simple (of course) and you can peruse the up-to-the-minute result of its invocation in my blog scanner on the keywords page for this blog. Perl:

sub keyword_tagger {
   my $ct = shift @_;
   my $weight;
   my $font;
   my $sm = 70;
   my $lg = 200;
   my $del = $lg - $sm;
   my $ret = '';
   foreach my $k (sort keys %kw_count) {
      $weight = $kw_count{$k} / $max_count;
      $font = sprintf ("%d", $sm + $del * $weight);
      $ret .= "<a href=\"/blog/kw/$k/\" style=\"font-size: $font%;\">$k</a>\n";
   return $ret;

This is generally not the way to structure a function call, because it works with global hashes, but y'know, I don't follow rules too well (and curse myself often, yes). The assumptions:

  • The only argument passed is the maximum post count for all tags, determined by an earlier scan of the tags while writing their index pages.
  • $sm and $lg are effectively configuration; they determine the smallest and largest font sizes of the tag links (in percent).
  • The loop runs through the tags in alphabetical order; they are all assumed to be in the %kw_count global hash, which stores the number of posts associated with each tag (we build that while scanning the posts).
  • For every tag, we look at its post count in the %kw_count hash and split the difference in percentages between $sm and $lg -- then format the link with that font size. Obviously, this is a rather overly hardwired approach (the link should obviously be a configurable template) but as a prototype and for my own blogging management script, this works well.

For our file cloud builder, we'll want to do this very same thing, but in Python (since that's our target language). But porting is cake, now that we know what we'll be porting.

Thus concludes the sermon for today.

So my first actual weekly application is finished now. Aren't you proud? Suffice it to say that even a minor app takes a few hours to put together when you're reworking all your programming tools at the same time. A character flaw, I suppose. I never use an already-invented wheel if I have a perfectly good knife and wheel material. And I never use an already-invented knife if I have a perfectly good grinder and stock metal. And I never use an already-invented grinder if I have a lathe, motors, and a grindstone. And I never use an already-invented lathe... (sigh).

At any rate, it took me a few hours more than I wanted, but I'm reasonably pleased with the result. You can see the whole thing here (it's far too long to publish on the blog directly, of course). Go on. Look!

For some time, in the context of my workflow toolkit, I've been thinking intensively about UI design in wxPython.

See, once I was embroiled in a rather extensive project developing a GUI application under wxPython, and frankly, the UI was unmanageable. It had been developed with some IDE tool or another, but the output was Python code. It was horrible, trying to find what was what and on which panel it was developed and what its ID was -- ugh! This was back in about 2001.

At that point, I hadn't really started integrating wftk into Python yet, but I dabbled in it over the next couple of years, always with the notion that the UI is most sensibly defined in XML, and that a sensible UI manager would then take that definition and build all the objects needed to implement it in wxPython (or, for instance, online in a portal or something). And since that time, other people have naturally had many of the same ideas, and you see this implemented. But I've always wanted to finish my own implementation.

The current app for that I'm working on is, of course, a GUI app (at least, some of the time.) And so naturally I have relived my need for my UI design notion -- and in the context of working on the file tagger, I intend to start implementing the UI module. On that note, here is a tentative UI definition sketch for the file tagger. Ideally, we could use this XML not only to generate the app itself, but also to generate documentation for the UI design (by transforming it with XSLT into SVG, for instance; wouldn't that be indescribably cool?)

All of this is, of course, subject to radical change. Here goes:

    <tab label="Cloud">
    <tab label="Files">
       <splitter (some kind of parameters)>
              <radio value="something" label="All"/>
              <radio value="something" label="Some"/>
           <button label="Show"/>
         <col label="Name"/>
         <col label="Tags"/>
         <col label="Description"/>

I already have a framework for that definition to go into -- I wrote that in, like, 2002 or so. But I never got further than definition of menus. So here, I'm going to implement frames, and at least one dialog.

Note that what's utterly missing from this is any reference to code to handle events. That will come later, when I see what has to be defined where to get all this to work.

And on that note, I close.

At long last, I managed to finish development on a first cut of the filetagger application. It took far longer than I really wanted it to, because I spent an inordinate amount of time whipping the wxpywf framework into shape (about a month) and so the whole "app a week" thing is more like "an app per five weeks" or so. Ha.

But you know what? I did it! I actually brought a major new module of the wftk, one I'd been thinking about for three years, to the point where it can be used. Wow.

So I'm glad I took the time to do it the way I wanted to do it.

Here are some of the features of wxpywf I created and used for this app:

  • XML definition of the entire UI of an application, using frames and dialogs. In comparison with the traditional call-by-call technique for setting up a wxPython UI, this is incredibly convenient.
  • Application-specific code grouped into simple commands.
  • Each frame and each dialog automatically binds to an XML record which can be addressed on a field-by-field basis.
  • HTML can be used for more textual interfaces; links generate commands which can have arbitrary effects on the UI (in this case, clicking on a link in the tag cloud switches the tabbed frame to the file list and displays the files with the tag selected.)
  • So far, the UI can include tabsets, list controls, HTML windows, rich text controls, checkboxes, radio button groups and listboxes, command buttons, and static text.

There's a lot of ground still to cover. But in my experience, that kind of ground can be covered in small, manageable steps after initial usability is there. And initial usability is definitely there. I feel really happy about this.

I posted v1.0 of the filetagger in the new PyPop format. The XML definition of the app is 310 lines and about 12K. I think this could end up being quite useful.

The code is here -- I don't have the actual running PyPop up to run it, though. I still want to get registration of file extensions working -- oh, yeah, and what there is of the help system. The help text is included but there's no command to display it yet.

If I end up defining a basic XSLT processor on top of the XMLAPI, this could start to get really interesting...

Finally! I've been pretty busy with the paying work this last week, and also with biochemistry due to my son's kidney/allergy problems, and so lowly open-source work has suffered.

But the PyPop GUI framework is ready to download in a convenient NSIS installer. Rather than host it, I've put it up onto the the SourceForge download page for your downloading pleasure.

Once it's installed, download the filetagger app definition and play around with it. It's all still pretty crude, but I'm having fun. Did I mention that this actually involves the on-the-fly generation of a Python class based on the XML application definition, which is then instantiated in the GUI to do the work? That was fun!

Anyway, more later. I'm still on week #3 of the app-a-week thing, for, um, the second or third week. Maybe I'll slowly approach an app a week as I get this stuff under control. Wish me luck!

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.