Archive for August, 2010

Grantlee version 0.1.5 now available

August 27, 2010

The Grantlee community is pleased to announce the release of Grantlee version 0.1.5.

The release contains several bug fixes and makes it possible again to build Grantlee with Qt 4.5 again. The most significant part of this release though is that Templates can now be cached and rendering Templates is almost threadsafe. Prior to this release there were several template tags which stored state while being rendered. The cycle tag is a good example of where this is a problem, and many people complain about it. Because the template stored and modified some state while rendering, the second and subsequent renderings would not not start with a clean state, and would not produce identical output in all cases. That meant that Templates are often discarded right after use and reloaded later. It also meant that Templates had to be loaded from the file system on each access even if they were accessed very often, otherwise the cached version would be volatile and contain the wrong data.

With a change in the system to make the Template::render method re-entrant, state is no longer stored in the Template itself, but in a RenderContext object. An instance of that object is available to templates while rendering to store mutable data. Additionally, that would mean that a single template can be rendered by multiple threads at the same time which could be significant if using Grantlee for a mail-merge functionality. Unfortunately, due to a twist in how I implemented escaping in Grantlee, that version of render() is not threadsafe yet. That should be solved in a binary-incompatible release of Grantlee in the future as well as making the render() method const so that third party template tags must be re-entrant.

Changes so far in Grantlee do make Templates cache friendly though, so I introduced a CachingLoaderDecorator which can be used to cache any Templates loaded by a TemplateLoader. Do for now at least, worse is better.

Advertisements

KIdentityProxyModel does nothing, fast

August 25, 2010

It has been brought to my attention that I have not blogged in a while. That usually means it’s time for a new proxy model.

The latest one is KIdentityProxyModel. It maintains an identity relationship to its source model such that the structure in the proxy mirrors exactly the structure in the source model, without sorting, filtering, flattening or otherwise changing the structure.

KidentityProxyModel in action

What the KIdentityProxyModel does provide though is a base class suitable for data proxying. There are many uses for such a class. Typically, an implementation of QAbstractItemModel will have an implementation of the data() method with a large switch statement for returning the decoration, the tooltip, the what’s-this text etc. It becomes cumbersome and difficult to maintain. Better of course is to use separate proxy models instead of a switch statement. If your tooltip text is defined in a ToolTipProxyModel, you can compile it in on the desktop, and compile it out on mobile/touch platforms where they make no sense. Similarly, you can define a DecorationProxyModel to return images of different sizes for desktop and mobile use. In KDE PIM we already use it to color the folders in kmail if you are reaching an IMAP folder size limit. Another use I have for it is to make any model have checkable items with the KCheckableProxyModel. (Ok, so I made two new proxy models 🙂 ).

KCheckableProxyModel makes check state available through a QItemSelectionModel

The primary reason for a class like this is separation of concerns, a separation of platform code and re-usable components. The overhead of using a KIdentityProxyModel is very small, so even using multiple proxies does not incur a great cost. I haven’t made any benchmarks, so I offer only proof by inspection.

After writing this class I was informed that something similar used to exist in Qt4 as QProxyModel, but was deprecated some time ago. I didn’t even know it existed. Its implementation is very similar to KIdentityProxyModel, but an important difference is that KIdentityProxyModel implements QAbstractProxyModel, while QProxyModel implements QAbstractItemModel. That means that chaining is possible with KIdentityProxyModel, but not with QProxyModel.