Andrew Wilkinson

Random Ramblings on Programming

Archive for the ‘djangode’ Category

Deadlock On Exit With PySide And QFileSystemWatcher

leave a comment »

Keys by bohmanLast year Nokia started developing their own Python bindings for Qt, PySide, when they couldn’t persuade Riverbank Computing to relicense PyQt under a more liberal license. While developing DjangoDE I made the choice of which library to use configurable. When running under PyQt everything worked fine, but when using PySide the program hung on exit.

Using gdb to see where it was hanging points to QFileSystemWatcher, which has the following comment in the destructor.

Note: To avoid deadlocks on shutdown, all instances of QFileSystemWatcher need to be destroyed before QCoreApplication. Note that passing QCoreApplication::instance() as the parent object when creating QFileSystemWatcher is not sufficient.

The following code will demonstrate the issue.

import sys

#from PyQt4 import QtGui
from PySide import QtGui

app = QtGui.QApplication(sys.argv)

file_browser = QtGui.QTreeView()
file_model = QtGui.QFileSystemModel()
file_model.setRootPath("/")
file_browser.setModel(file_model)

file_browser.show()

sys.exit(app.exec_())

As the comment says, we need to ensure that the QFileSystemWatcher object, which is created by QFileSystemModel, is destroyed before QApplication. To do this we can connect to the lastWindowClosed and ensure that the QFileSystemModel is fully destroyed.

import gc

def app_quit():
     global file_browser
     file_browser = None
     gc.collect()

app.lastWindowClosed.connect(app_quit)

It’s not clear why this code would work on PyQt and not PySide, but it is clearly related to the order the objects are deleted. Given the comment in the Qt documentation though you should probably not rely on it working on PyQt and ensure yourself that the QApplication is the last Qt object to be destroyed.


Photo of Keys by bohman.

Written by Andrew Wilkinson

March 14, 2011 at 1:32 pm

Posted in djangode

Tagged with , , ,

Unittesting QSyntaxHighlighter

leave a comment »

Testing 1, 2, 3 by alisdairI’m using test driven development while building my pet project, DjangoDE. A key part of an IDE is the syntax highlighting of the code in the editor, so that’s one area where I’ve been trying to build up the test suite.

To test the syntax highlighter the obvious approach is to send the right events to write some code into the editor the check the colour of the text. Although the QT documentation is usually excellent, it doesn’t go into enough detail on the implementation of the syntax highlighting framework to enable you to query the colour of the text. In this post I’ll explain how the colour of text is stored, and how you can query it.

A syntax highlighting editor is normally implemented using a QPlainTextEdit widget. This object provides the user interface to the editor and manages the display of the text. The widget contains a QTextDocument instance, which stores the text. To add syntax highlighting you derive a class from QSyntaxHighlighter then instantiate it, passing the document instance as the parameter to the constructor. This is explained in detail in the syntax highlighter example.

The document stores the text as a sequence of QTextBlock objects. These store the text as well as the formatting information used to display it. You might think that you can just call QTextBlock::charFormat to get the colour of the text. Unfortunately it’s not that simple as the format returned by that call is the colour that you’ve explicitly set, not the syntax highlight colour.

Each QTextBlock is associated with a QTextLayout object that controls how the block is rendered. Each layout has a list of FormatRange objects, accessible using the additionalFormats method. It is this list that the QSyntaxHighlighter sets to specify the colour of the text.

Now we know where the colour information is stored, we can find out what colour a particular character will be. Firstly you need to find out which QTextBlock the text you want is. In a plain text document each line is represented by a separate block, so this is quite straightforward. You then get the list of FormatRanges and then iterate through, checking to see if the character you want is between format_range.start and format_range.start + format_range.length

For an example of this you can check out the test file from DjangoDE here


Photo of Testing 1, 2, 3 by alisdair.

Written by Andrew Wilkinson

February 16, 2011 at 1:20 pm

Posted in djangode

Tagged with , , ,

DjangoDE 0.1 Released

with 14 comments

Op de laptop by romyboxsemI spend most of time at work building websites in Django. My editor of choice until now has been Kate with Chromium open on another screen. Most of my co-workers use VIM inside a PuTTY session to do their editing. With multicore machines with gigabytes of RAM, surely there’s a better way?

I investigated the current state of Django IDEs and came to conclusion that none of them are that great. Most are a plugin to a giant IDE that tries accommodate many different languages, so each feels like second best, or they are designed more for traditionally programming and not webdevelopment so they don’t integrate with Django’s in built server and don’t support editing Javascript, or provide a built in webbrowser. I also don’t want to have to pay for the editor, which limits my choice even more.

Having decided that none of the existing IDEs quite fit my requirements I did what any self respecting open source programmer with an itch would do, I headed to Google Code, created a new project and then got coding.

DjangoDE Main Editor Window

The project has now reached the stage where I feel I can make my first release, although this is a release that is very much in the spirit of the open source mantra, “release early, release often.” The key features are all in place, which I’ll talk about below, but they’re all extremely basic and it’s not ready to be used as a day-to-day editor. If you’re looking for a Visual Studio replacement, this is not it.

The source can be downloaded from the project site, or PyPI. The simplest method is just to run sudo easy_install djangode. You’ll need to have PyQt and of course Django installed. This first release also requires Linux, but being a Qt application that requirement will not exist for ever and it will eventually work on Windows (and hopefully Macs too).

DjangoDE uses the manage.py file to define the scope of the project. The “Project” menu bar lets you pick a manage.py file to load, or to create a new Django project.

The editor has a partial syntax highlighter for Python code implemented, and a quick access bar on the left of the window which lets you jump straight to the view implementing a particular url. It also has a tab for each application that is active in your project which lists the models.

When you open DjangoDE it’ll show you the Django project website in a tab. If you enter “/” into the address bar it’ll load the front page of your website.

Pressing F9 while viewing a source code file will create a breakpoint. If you then use the browser to view a page that passes that line the code will break and that point and the debug bar will appear. This shows you the variables in the current scope.

It’s very early days for this project, but these features will be fleshed out in the coming releases. I’d like to encourage people to post issues if they come across bugs or want features implemented. You can also contact me through Twitter as djangoide.


Photo of Op de laptop by romyboxsem.

Written by Andrew Wilkinson

January 24, 2011 at 1:28 pm

Posted in djangode

Tagged with , , , ,