To help me debug the small app i'm currently working on (which should be finished soon, i'm mostly in the "moar tests, squeeze bugz!" phase now), i've implemented a simple Qt widget which acts as an output console.
At first, i went for the overkill and tried to embed IPython in the app itself, thinking it would be so freakin kewl to be able to mess with the code in real time. Turns out i still suck too much for that kind of things, as i couldn't figure out how to actually do it (I got close on a copple of tries, but i forgot the details).
So after wasting about two days on this, i gave up and went for a more straight-forward solution.
The QDbgConsole widget (which i probably should rename, as i can see it being useful for other, non-debugging purposes) is a simple QTextEdit, preset to a default size and a read-only mode (Since it inherits directly the QTextEdit widget, those settings can easily be changed by using the base class methods).
The only trick is that it also contains a StringIO buffer, and exposes its interface to the outside world, turning the widget itself into a file-like object. This makes it possible to pass a Console instance to any function dealing with file objects -- I used this so that i could use the widget directly as a StreamHandler for logging.
The only file API method i've redefined is the write() method, which adds the passed message to the QTextEdit's contents before writing it to the buffer. Other methods could be redefined as well if needed.
I've posted the whole widget's code on gist, so go there and grab it if you're interested.
As a quick exemple, here's how i'm currently using it:
# Instanciate the QtDbgConsole widget
dbg_cons = qtdbg.QDbgConsole()
# Initialize the logger
logger = logging.getLogger('my_logger')
# Use the dbg console as a stream handler
ch = logging.StreamHandler(dbg_cons)
# Other handlers (in my case, a regular file handler)
# Create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(levelname)s - '
# Add the handlers to the logger
I've let some setup code in, but once the widget is instanciated, all that really matters is the StreamHandler creation and its association to the main logger. The StreamHandler is then responsible for using the console's write method when needed, and i never have to worry about it again (Except at app closing time, but that's mostly due to the way i'm using/displaying the widget. I'll detail this in a future post or add it to the code's documentation; i don't want to clutter this post too much).
It's nothing really fancy, but it should prove quite easy to reuse and i can see this comming handy in quite a lot of Qt Apps, even if only as a tool during developpement.
I haven't bothered testing it with python 2.7 yet, cause I can't be bothered to install a second instance of PyQt. This bastard is huge and I really don't need the space waste for now. I'll try it and update it as soon as I get a chance, tho.
(Actually, I already know it will fail when importing the StringIO class, but i haven't bothered fixing this since i can't test the rest of the code).