Preface

Two commonly touted aspects of Python are the readability of its code and how quickly it can be used to creating working applications. Among the complaints regarding C++ are legibility of complex applications and difficulty in debugging the same. The flourishing number of programming languages and flight from C++ to scripting and just-in-time compiler-based languages over the past decade (or two) forced developers to take a deep, hard look at the development process. Why is it that a language that can be so obfuscated as C++ remain able to do what others cannot? I won’t go into the reasons, because that’s a holy war on its own. The end result of the rise of Java, Perl, and other web-development languages that followed, along with the failure of so many languages to topple C++ is a deep retrospective among developers and engineers on the design and development process. Concepts like unit and integration testing, rising and falling popular “styles” of development (e.g. Agile, Waterfall, Extreme Programming), and the examples of both successful and failed open-source development models are changing the way software development happens.

Trains Don’t Turn Easily

Anyone who’s worked with undocumented and badly written legacy code will tell you that it’s a terrible, terrible thing. Poorly designed APIs, non-descriptive variable names, and the fear of regressions in mature code (what might be called the “if it’s worked this long, don’t touch it” effect) hound application developers. Once a library or application reaches a certain point in size or development milestones, fear of breakage spells doom for mistakes made early in the development process. If software were mansions, a warped support beam on the first floor is hard to fix when you’re putting up the third floor. Wooden roller coasters are infamous for this problem: a 2-by-4 off by an 1/8″ at the base can become three feet at the apex.

Once It’s Done, It’s Hard to Undo

The larger the application, the more time needs to be spent in the design phase. Unfortunately, until the code is written, compiled, and tested, some things just aren’t obvious. Unit and integration testing certainly help here, particularly if modular programming is properly adhered to. Nevertheless, compiled languages like C++ make revisiting the design phase after development begins is a painful process. An application written entirely in C++ can be written slipshod to get it working or slowly to do it right, but not both. Writing modules in Python first saves time by making mistakes and pitfalls visible early on and quickly repairable. Because Python is designed to be easily readable (assuming one doesn’t use get too clever with some of the core libraries), it can be used as an intermediate stage between design and implementation to get the algorithms right, tweak the APIs, and generally make sure ideas that are time-intensive to implement will work.

It may seem foolish to write a program twice, but that’s not what I’m advocating at all. Python is such a flexible language that it is possible to write code that closely mirrors C++ and can be reused with a little scripting. In the case of Qt and PyQt (or PySide) this is particularly true, as most of Python and C++’s core libraries can be replaced with their QtCore counterparts.

I will be following this relatively short post with a more extensive discussion on writing legible Python code that readily converts to C++ and how to go about doing so.

Qt5 just hit Alpha a few days ago. I have a number of thoughts and concerns about the new edition of Qt. Major releases–like 4.x to 5.x–typically are the time to do major reorganization, feature additions, and API changes. Typically, such a major release is a time to worry less about bug-fixing and incremental improvements and more about merging major projects or revisions that might break things. It’s a time to take risks.

The current project plan for Qt5 concerns me. Some of the new stuff is great, but the planned replacement of the (very flawed) model/view framework doesn’t seem to be surfacing. I’ve been frustrated with the idea of Model-View-Controller being replaced by Model-View since I started working with it, and KDE’s shift to a MVC back-end for KDE 4.8 really brings it home. The MVC Dolphin now uses comes from work QtLabs did quite some time ago as an intended replacement for the current model/view framework. I had hoped that Nokia/Trolltech would pick up on this and make the current model/view framework part of a legacy library, but this doesn’t look to be the case.

Internal documentation for Qt (the code itself) and various project plans refer to QFileSystemWatcher as flawed. Qt’s called for ideas regarding an alternative, but I haven’t seen discussion on this. I had also hoped that QtLabs would release something along the lines of a QWinFileSystemModel. A common complaint among programmers, C++ and Python alike, is that access to Windows shell functionality is limited. With Windows 7, Libraries are in increasingly painful missing component in Windows support, and not having the “My Computer” root node in a QTreeView paired with QFSM is a UI no-no.

That segues into something else that concerns me. While I realize that cross-platform portability is key for Qt and mobile support Nokia’s primary emphasis, Qt is still the primary alternative to Microsoft’s libraries for Windows development. That’s a source of funding and support for Qt’s existence and growth that shouldn’t be neglected. I doubt Nokia cares about licensing incoming from Qt anymore, but the more developers who are familiar with and use Qt for Windows, the more it will see adoption in the mobile arena. Creating a separate library for Windows-specific support (like ActiveQt) is just common sense. Not having to “roll-your-own” is a big part of Qt’s appeal, and Windows developers presently have to do for a large portion of Windows Shell integration. QFileSystemModel is just the most obvious example of this.

I’d also love to see two related features that are cross-platform: elevation requests and recycling bin/trash support. Presently, denied requests for file operations due to insufficient privileges leave the developer hanging. For GUI applications, being able to call native sudo and UAC functionality for such operations would be delightful. The same would go for adding a function to QFile to trash/recycle files. A simple check to see if the running application is an instance of QApplication would bring up a native recycle or trash dialog; otherwise, QFile::remove() would be called.

Integrated file compression support, such as Qt wrappers bzip2, lzma, lzop gzip and other patent-unencumbered compression algorithms would be wonderful. I realize that libraries exist for this, but a Qt library to wrap this functionality would 1) be cross-platform and 2) make the lives of developers easier. Since Qt is increasingly modular, this wouldn’t bloat QtCore and offer API consistency in file operations. Compressing files is, well, it’s just something that happens often. Adding a library to support file compression and decompression seems to make sense to me.

On a related note, I’d love to see support for Windows icon files. I realize Qt has QImagePlugin for this, but it wouldn’t hurt to throw in support for something used so frequently by Windows developers. Again, avoiding rolling-your-own is good.

I feel as if I’m berating Nokia, but ignoring desktop developers (particularly on Windows) is just a bad idea. The rapid pace of development for mobile devices is wonderful, kudos, the more the merrier, but with the weight of Nokia behind Qt now, continuing to support desktop developers is not a difficulty. I would particularly point out that many mobile apps have desktop counterparts (Kindle comes to mind). If Qt shores up their desktop support, the incentive to use Qt for mobile devices goes up. Software companies whose use Qt can shift from mobile to desktop development relatively easily if the toolkit remains up-to-date in both areas, this only increases the incentive to use Qt. With Qt now being primarily community driven, this will only further increase the pace of development. It’s cyclical.

I’ve been using PyQt for about two years now. Mark Summerfield’s books on Qt, PyQt, and Python are and have been a great help. If you program in any area he’s written on, I highly recommend checking his work out. His PyQt and first Qt book are a bit dated, but provides an awesome introduction. The new Advanced Qt Programming is great in the areas it covers, but it’s expensive and given the size of Qt, can’t cover everything. Nevertheless, it has some great work on threading and other areas that are useful. His other book on Qt using C++, C++ GUI Programming with Qt4, is definitely dated but a wonderful introduction to Qt. If you’re programming Python and PyQt, it’s still easy enough to follow conceptually and most of it translates to Python.

N.B.: The rest of this post discusses Python 3 or v3-style PyQt programming, which uses built-in Python classes to replace many Qt classes. The most prominent of this is replacing instances of QSting with Python’s str. It is my understanding that this is supported in Python 2.x, so it should still be applicable.

There are two areas of PyQt, however, where Python excels beyond that of the pace with which it can be developed. I discovered PyQt’s signal/slot model before keyword arguments, but they are both gems. PyQt handles Qt-style properties in a manner very similar to Python’s properties with only minor differences. Because of that, they didn’t make my Favorite Little-Known PyQt Features list. First up is what the PyQt documentation calls new-style signals and slots. It’s elegant, clean and simple.

With completely C++-like “old style”–as the documentation calls it–signals and slots, connecting a QToolButton to a slot would look like this:

QObject.connect(self.startButton, SIGNAL('clicked()'), self, SLOT('startDownload()'))

If we throw in a little Python, it looks like this:

QObject.connect(self.startButton, SIGNAL('clicked()'), self.startDownload)

That’s a little clearer, but it’s not “Pythonic” (I really don’t like that term, but it’s true here). Here’s how it looks using new-style signals and slots:

self.startButton.clicked.connect(self.startDownload)

I’d call that a much cleaner way of doing things. We can take this a step further to support overloaded signals. Imagine a QComboBox with the currentIndexChanged() signal, which can have a QString (str in PyQt) or int parameter. Getting this to work is pretty simple, too: we index the parameter type. For example:

someComboBox.currentIndexChanged[int].connect(self.fooMethod)

PyQt treats the currentIndexChanged() signal like a dict to pick which of the two signal signatures to connect, using the class type as a key.

Next up is using keyword arguments for Qt properties and signals during QObject construction. Consider how our imaginary startButton QToolButton would be constructed, C++ style:

self.startButton = QToolButton(QIcon(‘./images/start.png), ‘Start’, self)
self.startButton.setObjectName(‘startButton’)
self.startButton.setEnabled(False)
self.startButton.setCheckable(False)
self.startButton.setToolTip(‘Starts the download.’)
self.startButton.setIconSize(QSize(32,32)
self.startButton.clicked.connect(self.startDownload)

I threw in the signal connection for a reason, which I will explain in a moment. One thing that C++ features and Python lacks is method signature overloading, a necessary loss given Python’s dynamic nature and duck-typing. SIP transparently handles this for us, so PyQt still works nicely with Qt’s frequent function overloads. I mention this because of the first line, where I used the QToolButton(QIcon, QString, QObject) signature as opposed to QToolButton(QObject). It’s a small thing, but try implementing that in Python–it sucks. Consequently, some Python zealots would argue that it’s not very Pythonic. Anyway, let’s get fancy.

PyQt implements support for setting Qt properties during the Python __init__ call after creating the C++ object it wraps, and it does this via keyword arguments. To take advantage, we can just tail any property names as keywords during the constructor call. In fact, it’s even possible to completely exclude any non-keyword arguments, which I will do. Converting the above example to completely keyword argument-based __init__ call might look like this:

self.startButton = QToolButton(parent=self,
                               objectName=’startButton’,
                               text=’Start’,
                               icon=QIcon(‘./images/start.png’),
                               enabled=False,
                               toolTip=’Starts the download’,
                               iconSize=QSize(32, 32),
                               clicked=self.startDownload)

Boom. Using this method has a number of advantages. First and most obviously, it’s faster to type. Secondly, it clusters things a little more neatly and list-like, which makes it easier to read (and modify). Also, note the signal connection on the end. I haven’t tried to use keyword arguments for overloaded signals (as in the QComboBox example) before, and I doubt it would work. I should mention a caveat I’ve run into regarding signal connection by keyword. I usually lump all of my signal and slot connections in a method I also usually call connectSignals()–I’m tricky with names like that. Doing this makes it easy to see exactly what signals/slots are connected, modify them, and selectively disable if necessary for debugging. Having an extraneous signal connected elsewhere–even if it’s for a QPushButton connected to QDialog.close()–is a little out of place. If you lump your signal connections in the same way, be aware that connecting signals by keyword argument can become an issue.

All right, that’s it for now. Happy New Year.

Qt 4.8 (and the equivalent PyQt release) came out just in time with multithreaded http support and some other functional improvements. I mention multithreaded http primarily because I’m working with QtNetwork right now, and threading a simple dialog-based application would be a pain. Thankfully, I hadn’t attempted that portion of the code writing process yet–althought I have had to design with threading in mind. I can forget about dealing with that aspect now, gratefully, and focus on getting this &@#$% to work. I redesigned a few aspects of the code, but it’s ugly enough on the internals that I’m going to need to rewrite a lot of things.

The ideas are churning, and that’s good.

I’m sitting at work (Starbucks) typing up a random blog entry to get back into the habit of the blogging phenomenon. I couldn’t tolerate the old four sidebar style, so I’ve changed the blog appearance. Development on KyUI is halted temporarily while I teach myself QtNetwork. I’ve got two new widgets to throw into the mix, one based on work from another PyQt programmer. I’ll talk about that once it’s presentable. There are other ideas churning, but I’d rather not get into them until I actually make…what’s the word?…progress.

Working with QNetworkAccessManager is interesting. I converted the PyQt-converted-from-Qt example for QHttp to QNetworkAccessManager, and the results were less than inspiring. QNAM (as I’ll abbreviate it) decided my Internet access was unavailable with a decidedly confusingly generic error message. I’m writing a tidbit of software that reads in HTML, grabs information out of it, and generates the appropriate link to a wallpaper JPEG without running through intermediary HTML. It’s teaching me QtNetwork and managing lots of signals and possible error conditions. I have to admit that–after some heavy cursing–QNetworkAccessManager is better than QHttp, particarly with the use of QNetworkReply as a QIODevice. The one feature of QHttp that I miss is using QNetworkAccessManager.get() to funnel a request directly into a QIODevice, specifically a file. Yes, QNetworkReply is an io buffer, but it would be nice if I could call get(QNetworkRequest, QFile) and wait for the finished() signal from the QNetworkReply it returns without waiting for the readyRead() signal and chunking data into the file. Just a thought.

Other thoughts: contentsMargins should be a QProperty for QWidget and QLayout. I use keyword arguments almost exclusively to set initial QObject subclass states, and not being able to set the contents margins this way is irritating.

I’m off now…into The Cloud.

A year after my blog got hacked, I’ve finally bothered to restore and fix everything; White-Walls is back!

In the time that’s passed, my interest in PyQt4 and Qt simmered into actual UI development. I turned sketches and rough designs into working code, learning a great deal in the process. I apologize to Python 2.x programmers, but Python 3 is my flavor of choice. That said, all of the code should be easily adaptable into working Python 2.7 code for those who wish.

I’ve named the project KyUI, pronounced KYOO-ee, because Q-UI was taken. The goal behind KyUI is straightforward: programmers often have to recreate the wheel for their software, which is a waste of time. There are quite a few widgets and dialogs that are common to most desktop applications but are not provided with Qt and are unavailable as source without stripping from other OSS projects. The alternative that most developers are left with is to rewrite dialogs for things like setting hotkeys, tree widget headers, and toolbar buttons. Another simple example is adding a gripper to QSplitterHandle, which is lacks one by default under most styles.

I’ll be discussing various topics here about thoughts on user-interface design, ideas I have, KyUI progress, and how-tos for writing PyQt code that goes beyond Mark Summerfield’s excellent Rapid GUI Programming with Python and Qt, including keyword arguments, a quick-and-easy solution regarding enumerators (e.g. Class.EnumValue in Class.Enumerator working without complex fussing, named tuples, or custom classes)

I’ve also done some serious hacking with Doxygen to make the result look (mostly) like Qt’s internal documentation, which is also available in the SVN source tree.

Look for more later.

I’m reading through About Face 2.0 again, in more detail. I’ve come across the author’s chapter on Verb-Object and Object-Verb thinking with respect to user interaction. His introduction explains that Verb-Object was the original method of interaction, but that WIMP changed that. His point, essentially, is that the ability to interact with multiple objects requires the programmer to handle a more Object-Verb method of thinking.

The example provided goes like this: you’re in a grocery store. You pick out a number of items to purchase. The items are objects, and purchasing them is the verb. The example explains that this is, in essence, selection, which puts a kink in the verb/object order, because multiple objects may be acted on. My first thought on reading this, before I finished, was that the act of selecting is in itself a verb, preserving Verb-Object order. The author points out that a user chooses his objects before interacting with them, such as selecting multiple files for deletion.

In my mind, this is fallacious. Yes, it appears the object is designated first, but there are caveats from all three perspectives that count: the user, the computer, and the programmer. Firstly, selection is, in itself, an action. From the perspective of the computer, Verb-Object order is maintained. Like the clipboard, the selected items are added to a stored list. When a user enters a command (Verb), the computer checks to see if items are already selected. Since the user has carefully selected a number of files, that list is called up in lieu of a single item (or none, if none had been selected). The order, in Verb-Object thinking is this: Select: Item, Select: Item, [repeat n times], Delete: Selection. Verb-Object thinking is preserved from the computer’s perspective.

From the user’s perspective, the same is true: the user does not think, “File 1, select, file 2, select, delete”. Really, the user doesn’t think about selecting individual items at all, although his behavior is still Verb-Object oriented. The thinking follows more like “select items”, which is Verb-Object, followed by “delete selection”. Again, this is Verb-Object thinking.

To the programmer, Verb-Object thinking is simply mandatory. Functions, methods, or whatever the programming language being used calls them, are in essence, verbs or commands. They are passed arguments as objects. Whether using functional or object oriented programming, the action is always first. The programmer doesn’t define actions for every object, he defines actions that are given objects.

Okay, I’m done.

It’s been over a year since I’ve updated this blog. I hope to change that soon. I’ve installed ScribeFire again, which ought to help. Look for some new widgets programmed in PyQt for Python 3.1 soon.

I was reading an Ars Technica staff member’s blog on de-cluttering when I stumbled on this comment:

Suggestion: round up ALL of your spare hardware (every last cable and PCI filler plate) and bring it all to a new sorting area such as a garage space, living room, kitchen, whatever. Take it away from where it is currently stored.

Now sort through it with new eyes and get rid of all your old legacy stuff that you haven’t touched in five years. Give it to a friend, donate it to a school or nonprofit, but get it out of your way. Put it all in boxes and move them to a corner, preferably near an exterior door.

Now make a wish list of what you’d like your dream computer/electronics setup would look like. Go through the Ars system-building articles if that helps. Now scrutinize whatever hardware you have left and see if it fits at all in your future plans. Do you still have old 10/100 Ethernet hubs yet want to run GigE exclusively in the future? Move those hubs to the pile near the door. Still have an old USB-1 hub? It’s worth about fifty cents at a garage sale now. Do this until you’ve pared down everything to stuff you actually want to use in the future. Put it all back in boxes, a little better organized this time, and put it back on the shelves if you have them. (Step 1.1, omitted earlier: Buy more shelves!)

Only by physically moving everything away from its current inertia well can you really sort efficiently and a bit more ruthlessly. It will also
give you a chance to vacuum up seven years of accumulated dust. Do this, and then set yourself a reminder for five years from now to do it all over again.

Oh. Now that’s something to think about.

From jriddel’s Developer Journal

Qt, even though it’s been available for noncommercial use for quite awhile on Linux as GPL, is completely relicencing to LGPL–which means it’s “Free as in Beer and Freedom Free” for all the Stallman-esque obsessives out there. Not that anyone paid for Qt, really. Use for KDE, then for Linux, has been non-commercial for ages, but Nokia’s ownership and oversight of Trolltech means profit for the toolkit is unimportant. The more Qt, the better. One of their first moves was a quick open-sourcing of Qt for Windows.

So another set of kudos for Nokia! If you’ve been holding out on using Qt for whatever, don’t. If you’ve been using Gnome, I’m sorry. If you want to rediscover goodness in programming, do so. It’s LGPL/GPL goodness all around.

Also, since Qt is being actively ported to everything, try out QtCreator. It’s goodness in a cup and runs on both Windows and Linux. Don’t ask me about OS X, since I no usey teh losey. I kid, I kid. But I think it’s available for OS X, too. The whole thing is beta, but I’ve heard good things.

Last but not least, KDE 4.2 Beta is out. =)