Saturday, January 27, 2007

Stringing the public along

Ha! I simply haven't had time to look at publishing the PyPop framework yet, but I did go ahead and post the filetagger translated into that framework.

The expression of the filetagger now takes 310 lines of XML, and includes the specification of the UI, the commands behind it, the structure of the datafile, the handling of all command-line flags and arguments, the About dialog text, and the help file -- the Python code was about 340 lines and didn't include any of the textual resources. More importantly, the expression of the commands is somewhat more readable in the interpreted version, or at least I find it more readable and certainly more writeable.

The only sticky wicket is that I have no documentation framework for this style of coding yet. I've got some ideas on how to manage it, but (as always) little time.

Anyway, I'll get the interpreter for this little beastie up as soon as possible, and then things are going to start getting interesting.

WMI wizardry

So it turns out that there's an easier way to get to most of the Windows shell functionality, through the Windows scripting interface and -- even better -- WMI, the "Windows Management Interface" which is a huge, sprawling attempt to put all the administrative stuff in Windows into one scriptable place. There's a truly inspired Python wrapper from Tim Golden which provides wonderful introspection and scripting, and Microsoft also has an entertaining column on general scripting and WMI at Hey, Scripting Guy!

I've asked the Scripting Guys about how to move icons. I still think it ain't possible, although the quest has reminded me of a lot of Windows API stuff and also brought home to me how many (half-assed implementations of) nice mechanisms have arisen in the fifteen years since last I tried all this.

I almost have the PyPop GUI interpreter up and running for you. It's up and running but I want to add one more feature (the ability to register file extensions) before I release v1.0. Might happen today.

Friday, January 26, 2007

App #3 slight redefinition

Oh, hey -- it occurred to me after posting the last post that if I modify the requirements just a tad for app #3 I can still do what Cabin Tom really wants to do. Granted, it looks like it's just too durn much trouble to move icons on the Desktop, but I can easily monitor the Desktop and move all newly created files there into an incoming-download folder of arbitrary definition.

So mote it be. App #3 is now slighly adulterated, but at least possible.

(But if you know how to script icon-moving-around on the Windows Desktop, I still want to hear from you.)

Thursday, January 25, 2007

Guter Gott...

Oh yeah. Now I remember why I always hated working with Microsoft Windows. When I started delving into the guts of shell programming, for the first time in a very long time indeed, it was with a fairly relaxed notion that since the Desktop is a folder, the information about the location of the icons on the Desktop must be in a relatively easy-to-find location or have relatively easy-to-use interfaces.

I was wrong. Oh, granted, I'm pretty sure I've found something (IShellView2 exposes a SelectAndPositionItem method) but it took a day's reading, and that just isn't time I had. It escalated into a sort of obsession, and at the end of the day, all I have to show for it is maybe I can move the fricking icons around on my Desktop, for some versions of Windows.

I say "maybe" because there's no fricking documentation for it. That's a situation I run across in open-source programming, of course, but in the open-source world I could look at the code for Explorer and see how Explorer does it. Here, that avenue is closed to me, not because it's important for Microsoft to hide it, but because it's simply not important for Microsoft to divulge it. The default is secrecy. And that default is, at the heart of it, precisely what is wrong with the world in general. I won't go into the obvious political ramifications because I'm pretty sure if I started in on it I'd shock Dana's maiden heart, but suffice it to say that Windows sucks. Sure, it's usable -- has to be, to perfuse the market to this extent -- but it's just marginally programmable. And for no real reason.

Back in the Good Old Days, when I was doing a whole lot of VB programming under Microsoft Word 6.0, is when I first realized this about Microsoft's worldview. Even then, Word was quickly establishing itself as the industry standard for document editing and storage, and so there was no alternative. And I'll be the first to admit that exposing Word's innards in Visual Basic for programming was brilliant -- I loved it. But whereas the motto of Perl (a language I learned much later) is to make easy things easy and hard things possible, the unstated motto of Word Basic was to make easy things possible and hard things unimaginable. There were things I simply could not do, no matter how many weeks I spent hacking on them. (Back then, as a paid minion, I had the weeks to spend -- now it would simply be out of the question and on to the next project idea.)

With open source, the documentation is of comparable quality, but when the documentation gives out, there is at least some working example code in whatever product originally inspired the interface or function or what-have-you in the first place. The thing was written to solve a problem, and the solution is an open book. With closed-source, somebody obviously solved it, but they will not tell you the solution.

Ugh. I hate them all.

On the other hand, I have found lots of nice pieces for app #3 -- for instance, I can still build a directory monitor using SHChangeNotifyRegister. This installs a window to be passed messages from the Windows Shell (i.e. Explorer and the Desktop) whenever files are created, written, moved, deleted, etc. Instead of polling a directory on a timer, therefore, I can just sit hidden in the background until something happens. Much cheaper in terms of system resources.

And really, just getting that much working would be a valuable addition to my framework; I'll probably just call that app #3 like the coward I am, and call the icon mover action app#4, unless somebody can show me an easier way of going about it. The sticky wicket is that the Python COM model doesn't wrap IShellView2, so if I want to go that route I'll have to wrap it. And I don't want to. So you Windows mavens, now's your chance to show me how much Windows doesn't suck. If you can.

Monday, January 22, 2007

Another detour!

Well, as I was mulling over how much larger wx had gotten since I last downloaded it (and once I realized the smallest of apps, compiled, becomes 5MB), I got to thinking.

That's always a mistake.

In this case, I thought: gee, it's nice that the UI of these programs is defined in the XML. What if I defined the command-line argument handlers, too? And loaded the external data file based on that description?

What if ...

Then the epiphany struck. What if each of the commands in the CLI were to be defined in the XML? As Python, no wait, as templates to generate Python? So I researched it and bent my fevered brow to the task. And lo! it works.... Really.

If I define "filetagger.wftk" as a UI file, with an "action" tag for each command in the CLI, wxpywf can now read those, build the CLI class, and pass it back to pypop for instantiation in the main context. It can't import Python files, but it could without a whole lot of work. And will.

Now I can introduce a real Software Jedi toolkit: pypop. As soon as it's cleaned up, anyway. If pypop stores apps by name, you could download them with a pypop app manager, install them, and let'em go. If the pypop then subsumes both the Jedi console and a directory monitor and stuff like that -- well, you'll have a handy-dandy Swiss army knife of a UI tool. I kinda like this.

Anyway, I'll clean this up and get it posted tomorrow or the next day. And then continue with App #3.

Saturday, January 20, 2007

App #3 taxiing for takeoff

Today I got started on filemonitor, which is app #3. I really haven't done much yet except to research timers under wxPython, add a nifty "later" command to the wxpywf GUI CLI, sketch out a timer pseudowidget for repeated, scheduled commands, add a "hide" and a "show" command to the CLI so that we can hide on the system bar when in monitoring mode, and that's about it.

I don't yet have things set up to upload works in progress easily, so I haven't done that yet, but I'll probably do something along those lines over the next few days.

Friday, January 19, 2007

Wheel reinvention for fun and profit

It's come to my attention that some among you think it's a waste of time to reinvent the XML-described UI. Some such rot about "reinventing the wheel".

Strunk and White's Elements of Style has a nice little turn of phrase I've always liked: "Infinitives, like round stovewood, sometimes benefit from being split." To which I add that wheels occasionally benefit from judicious reinvention.

There are three responses to this complaint, actually. First is why I believe that it's not a waste of time to reinvent the XML-described UI wheel, and it's the same as anything else in this venture: yeah, lots of people describe UI in XML, for the simple reason that XML is specifically designed to describe things. There are, in fact, a couple of XML UI description frameworks already out there for wxPython. As I said at an earlier point -- I don't like them because I didn't write them: the flippant version of saying, "I don't like them because they don't do everything I want and they don't express things as elegantly as I like." There's a great deal of machinery behind the wxpywf that simply doesn't exist in any comparable framework I know of. The fact that it's XML-described is only the surface -- the thing is, by reinventing XML UI description in the context of my existing workflow toolkit, I saw that there was a great deal more that could be done to encapsulate the UI in the first place.

Essentially, the UI frame is itself now an XML-describable object at runtime. It is an array -- I can effect changes to the UI simply by assigning a variable, and the framework takes care of figuring out how to implement the actual visual changes. If you take a look at the actual code for the filetagger, instead of carping about wheel reinvention, this elegance becomes more apparent. And so yes, I think that this particular wheel did not suffer from gratuitous reinvention.

So that's one response, a nuts-and-bolts thing. The second is more of a philosophical nature, a simple refutation of the weird notion that There Can Be Only One. Is there only one database? Did anybody carp at the MySQL writers that PostgreSQL already existed, so they were just reinventing the goddamn wheel? Did sendmail's mere existence make it superfluous to consider any other mail handler? For that matter, what about Linux itself? Didn't Unix already exist? Didn't Windows already exist -- what's the point of writing a GUI environment for Linux, then? Python is a reinvention of Perl, Perl of C, Java of C++. wxPython is a waste of time given TK, and Tcl isn't a reinvention of anything recognizable but still manages to be a waste of time. Or so it would seem to this humble wheel reinventor.

A healthy ecosystem benefits from a great number of competing -- and symbiotic -- species. That's a point equally true of carbon and software. If you don't like my GUI framework, don't use it. But whatever you do, don't complain that I wasted "time" -- whatever the hell that is -- by writing it. Because reinvention is progress. It was reinvention of the basic fabric of society that gave us the American Constitution, and a reinvention of our attitudes towards the universe itself that gave us the Enlightenment. I maintain that I was not wasting time.

And then the third and lowest-level response: who the hell are you to complain about wasting time, anyway? Why the hell do geeks think anything of a time-wasting nature is an affront? Do I complain about people playing RPGs or watching football? Is that stuff inherently more useful than my coding? What did you do today that wasn't a waste of time? Still got a TV? Bet you watched 24. Talk about a waste of time! At least I have something to show for my time that's different from what ten million other oxygen sinks did.

Waste of time. I'll give you waste of time.

Thursday, January 18, 2007

Welcome to the XXIst century!

Yeah, so I finally upgraded my Python and wxPython versions. OK, so I hadn't upgraded since 1999, OK? OK? You got a problem with Python 2.1 and wxPython 2.3? Hey, they were good enough for us back then.

So now I'm on Python 2.4 and wxPython 2.8 and it only cost me a day of flailing around, realizing I hadn't compiled anything in C in an inordinately long time (two laptops ago, actually), trying Microsoft's new free MSVC environment, rejecting it due its stupid requirement of manifests for the runtime (who forces licensing for a C runtime? Microsoft, that's who) and switching back to MSVC 5.0, which was good enough for grandpa so it's good enough for me. That kind of thing. But now it all works again, and while the switch from Py2.1 to Py2.4 isn't going to get me much, there are a lot of fancy new widgets in wx2.8.

(As soon as I have another day to spare for it, I'm seriously going to migrate over to MingW32 and be done with MSVC for good. I've used MingW32, way way back when you had to handroll and compile your own Perl to run it on Windows, and it's a dandy compiler. But the wftk has a rather complex build environment on Windows, and getting that all to work right with a new compiler felt rather daunting yesterday. So I'll do it later.)

Primary among the fancy novelties in wxPython 2.8 is a nice class to put an icon on the system tray in Windows, and that was really what made me break down and do it in the end. Oh, no, I forgot -- the other reason is that to get to the Windows COM classes I need the Win32 classes but they don't support Python 2.1 any more. Not even available for download! So here I am, being dragged kicking and screaming into the new Python millennium.

Tuesday, January 16, 2007

App #3 on the runway

OK, we have a winner in the app implementation lottery: Cabin Tom's suggestion for a "file placement" utility. The idea here is simple: when downloading things to the Desktop, Tom is bothered by the fact that the icons for these downloaded files get scattered all through his carefully set up working icons. He'd prefer that the files get tossed into a separate part of the Desktop.

Since the Desktop is of course just a directory which gets special treatment, my solution is a two-parter:
  1. Reimplement miechu's directory monitor in a more generalized way, so that a generically specified action is taken whenever the contents of a directory change
  2. Implement an action for that utility to take which consists of modifying the icon properties of the file in the directory, so that they get moved into a specified area of the screen.
This is going to be a bit of a challenge for me, because I'm not at all familiar with the Windows classes to get this kind of task done. But in principle it ought to be easy. Right? Yeah!

Sunday, January 14, 2007

Whoops, documentation helps

Seems I neglected to mention that there is a command-line syntax for the filetagger (and didn't test it for absence of said command line). I've fixed both issues -- first, a new version is up that does the Right Thing if you don't give any command line arguments or naively click the executable, and second, there is a doc file attached to the zip which explains the command line, and it says this:

This is run from the command line like this:

filetagger1 -fcst[tag] [database name] [command]

The flags are as follows:
-f: show the Files tab when starting
-c: show the Cloud tab when starting (default)
-s: run silently, i.e. just execute the command given and quit
-t[tag]: in the Files tab, filter for the tag given.

The database name is required, hence the confusion. I hadn't tested for the case of no command line -- there's a new version up on my site which works better, assuming the database name 'default.ftg'. If you give a filename that doesn't exist, it'll be created when you add files.

Finally, the command can be one of the following:

add [filename] [filename]...

(In silent mode, no dialog will appear to elicit extra info; in that case, give it a tag with -t[tag] and that tag will be attached to the files you've just added.) If you don't give any files, a common files dialog will come up to let you pick some.

mod [filename]

Pops up a dialog to edit that file

del [filename] [filename] ...

Deletes the file(s) listed.

Here's what the Files tab (the file management half of the app) looks like:



And the Cloud tab (which comes up first by default) looks like this:



The whole thing is done with XML and mirrors and I'm really quite happy with the results. Now on to app #3. I'm not sure what I want to do next. Any ideas?

Thursday, January 11, 2007

At long fricking last! The filetagger is here!

OK, OK, I know this isn't anappamonth.com, but there was a lot I wanted to do right in this first serious application. And I'm quite happy with it! Tired, but happy. You can see the results of my handiwork here (code and download available there, too).

I did this app with my (now marginally working) wxpywf framework, which combines wxPython GUI with my XML-oriented wftk project. This framework started as a simple way to put together UIs for workflow applications under the wftk, but I lost development steam a few years ago due to many Real Life factors. That seems to be changing (insert vigorous wood-knocking here). The module has a few nice features:
  • 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.
Anyway, it works for this app. The filetagger fulfills most of the requirements I posted last month, and can easily be added to the SendTo menu and assigned to a file extension (although I leave those as an exercise for the reader at this point -- did I mention I'm really tired?) I didn't implement any export capabilities, for instance. But it would be really easy to do so.

It's a good first draft!

Friday, January 05, 2007

Haven't forgotten you all

But it looks like I should next create an app-to-week ratio meter, sigh.

The holidays did indeed intervene, and as I always suspected, getting my GUI framework into working shape was more work than I expected, but the task is near done. So tomorrow or so, I'll be treating you to app #2, the file tagger. It's kinda cool, and I find it elegant. And since so much of the effort has gone into making the framework elegant and reusable, my next app should really be done in a week (or less!) That's the game plan, anyway. This egregious Yuletide disappearance has just been an excuse to do this right, something I've been planning for years.

Onwards!