Archive for April, 2010

KDEPIM on Mobile – What’s going on?

April 30, 2010

Anyone following the commits in the kde svn repo will notice that there has been some action on the mobile front in KDE PIM over the last few months.

We reported from our annual meeting in Osnabrück that we would be working to get a PIM stack based on KDE and Akonadi onto Maemo and WinCE devices with the benefits and features that Kontact and the rest of KDEPIM brings desktop users today in stable versions of KDE PIM.

The target is a suite of Free Software PIM applications enabling strong encryption and privacy features along with separation of data to different contexts, for example work and home email and contacts. The solution must be flexible to multiple access and transfer protocols, and to multiple types of data as well as being realistically fast. The framework for the PIM platform is of course provided by Akonadi.

This project is the result of a collaboration of KDAB, (my employer) with Intevation, crypto specialists G10Code, and interaction specialists Apliki known to KDE for recent usability testing work on KMail icons.

Recently a milestone of readonly functionality prototypes was reached for all target applications, so I can start to show them off. It is important to keep in mind that visual completeness was not a target up to now, so all applications will likely change visually as we work towards finished software.

[blip.tv ?posts_id=3578942&dest=-1]
[OGG link]

In this video I use and kmail-mobile, kaddressbook-mobile, korganizer-mobile to access data on a remote Kolab server, the same that my desktop connects to. Much of the UI layer is implemented in QML, and the gestures support allows the use of swipe actions to for example expand slider panels on the side, flick through lists and go to next and previous items. The screenshots below are from my workstation which has different proportions to the phone, but shows the functionality more clearly if you can’t hold it in your hand.

KMail-mobile provides a navigation tree on the left and a list of emails on the right.

When a collection is selected, its child collections are show below it. The "current" email shows some more information

Selecting an email makes it readable in fullscreen mode.

All of the applications feature a start page to select an account or configure favorites

KAddressbook-mobile uses a similar account navigation method to KMail-mobile

The expanded view shows the same information as the current KAddressBook

KOrganizer-mobile features an agenda view as the central component

The event detail view is shared with KOrganizer

The start page of KOrganizer-mobile also allows chosing a date-range to browse

The KDE PIM platform provides a large versatile base for pim applications of different form factors

Much of the code implementing the mobile application functionality is shared with the desktop versions of the applications. We estimated before that it should be possible to share up to 80% of the code between them. Of course, should does not mean *will*, but sometimes it can. 🙂

Advertisements

Breadcrumbs for your view

April 21, 2010

Something caught my eye in the recent release announcement of libQxt 0.6.0:

  • Added QxtCrumbView::crumbDelegate()

I was recently working on some model/view code for breadcrumbs, and this looked like it solves a similar problem, but I could already see it took a very different approach to mine.

A QTreeView and a QxtCrumbView

The idea is to create a list of the breadcrumbs above the one item that is currently selected. That means picking out one item from several levels in a tree and putting it in a list. Rather than putting the logic of creating breadcrumbs into a view, I put it into a reimplementation of QItemSelectionModel. I know, I’m pretty predictable.

The KSelectionProxyModel shows the content of a QItemSelectionModel if configured with KSelectionProxyModel::ExactSelection. That means that if I could programmatically create a QItemSelection representing the breadcrumb, I was already on a home straight. The KBreadcrumbSelectionModel encapsulates the concept of “When an item is selected, make a selection which includes its parent and ancestor items until the top is reached”. Like before, this is accomplished with an override of QItemSelectionModel::select.

QTreeView and BreadcrumbNavigationView

The advantage of having the logic of creating the breadcrumb in a proxy model is that it is independent of any ui code, so the proxy model can be used directly to create a breadcrumb view in QML too.

Breadcrumb navigation enables the use of a tree model in QML

The QML there is far from what it should be visually, but as the model of “The breadcrumbs of a selection” is separate from its visualisation, that can be improved separately. I know people want to know how to put a Qt Tree Model into QML, because they keep googling for it :). Well it is possible.

So while the QxtCrumbView gives you a perhaps more ready-made solution, this approach gives you the pieces you need to create flexible breadcrumbs for multiple UIs.

Sharing a QItemSelection between views through proxy models

April 20, 2010

It is possible to share a QItemSelectionModel between two different views, and therefore to share the selection between both. The technique is used in the Chart example and the interview demo.

A QItemSelectionModel can be shared between views

However, in a complex application, it’s not as simple as a model and a view or two. Eventually someone finds an excuse to add a proxy model, but then you can’t share the selection anymore. If you try it you get a runtime error:

QAbstractItemView::setSelectionModel() failed: Trying to set a selection model, which works on a different model than the view.

QitemSelectionModel can not be shared when using a proxy model

The problem is that a QItemSelectionModel operates on one particular model, so views manipulating the selection through it need to be operating on the same particular model. When a selection is made, the indexes which are part of the selection get painted a different colour, so something in the system needs to know of the existence of the proxy model and do the mapFromSource work.

Luckily enough, the designers of the Qt Model View system had the foresight to make some methods of QItemSelectionModel virtual, such as select. That means that when a selection is made through the view, we can do something else than select the indexes, or something supplemental such as a mapToSource call.

The KProxyItemSelectionModel inherits and overrides the QItemSelectionModel methods to encapsulate the concept of "When a selection is made, proxy the selection to another selection model and vice-versa".

KProxyItemSelectionModel proxies selection to another QItemSelectionModel

It works in both directions, so a selection through either view is forwarded to the other. There is a sufficient amount of voodoo, documented with ASCII art, to allow arbitrary configurations of proxy models to be traversed as long as they share a common source model somewhere along the line.

Complex proxy structures are traversed automatically be KProxyItemSelectionModel

That’s not the only trick you can play with QItemSelectionModel. More in a later post.

Update: The KProxyItemSelectionModel has been renamed KLinkItemSelectionModel.

Grantlee Gems: Customizing plugin build output directory

April 15, 2010

I wanted to be able to to run all the Grantlee unit tests from the build directory without having to go through the install step. As the whole system is plugin based though, the plugins need to be sought and found in specified directories following a certain pattern. The pattern is ${Something}/grantlee/${version}/pluginname.so. For example, the default plugin in version 0.1 would be searched for in ${Something}/grantlee/0.1/default_tags.so for each value of ${Something} in the list QCoreApplication::libraryPaths.

That’s fine for running the tests against installed plugins. Well known library paths are searched for plugins. However, the output build directory for the tests is ${CMAKE_BINARY_DIR}/tests, and the output build directory for plugins is something like ${CMAKE_BINARY_DIR}/pluginname/pluginname.so. That doesn’t match the pattern /grantlee/${version}/pluginname.so, so my initial solution was to use the CMake install() command to install the plugins to a location inside the build directory. That unfortunately caused problems with packaging tools when testing with the OpenSUSE build service, and it wasn’t really an elegant solution.

The correct solution is to specify the directory the plugins should be built in. Instead of building the plugin to ${CMAKE_BINARY_DIR}/pluginname/pluginname.so, it should be built to ${CMAKE_BINARY_DIR}/grantlee/${version}/pluginname.so.

The magic to do that is to specify the ${LIBRARY_OUTPUT_DIRECTORY}. On Windows it’s ${RUNTIME_OUTPUT_DIRECTORY} in the set_target_properties command.

set_target_properties(${pluginname}
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/grantlee/${Grantlee_VERSION_MAJOR}.${Grantlee_VERSION_MINOR}"
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/grantlee/${Grantlee_VERSION_MAJOR}.${Grantlee_VERSION_MINOR}"
  )

Easy.

Grantlee Gems: Subclass of a Qt type in a QVariant

April 14, 2010

When creating html it is necessary to be mindful of escaping html entities properly. “&” needs to be replaced with “&amp;”, “<” with “&lt;” etc.

When serving html data remotely, the main reason for this is protection from XSS attacks. Aside from security concerns, having html entities escaped when they should not be is also a problem. If your html output looks like “<img src="president-cat.png" />” instead of showing you the actual image, you will be an unhappy user.

The Django Template System uses a subclass of the python type string extended to also store information about whether the string should be escaped or not. A string that should not be escaped anymore is “safe”. The task was to create a type which can be used just like QString, but which also stores information about whether the string is safe from further escaping or not. Additionally, certain operations on the object need to change the “safe” state of the string. Even though the string “Kernighan &amp; Ritchie” is safe, if the developer does something like str.remove("amp; Ritchie");, the result is not safe: “Kernighan &”. So remove is an unsafe operation, but it’s not the only one. Unsafe operations on QStrings need to be reimplemented to make unsafe operations turn a safe string into an unsafe string.

The thing about python is that all methods behave as virtual, all classes always behave polymorphically and it is largely type independent, though types must often conform to some concept. That means that in python the solution was to create a subclass which contains the safe/unsafe variable and which re-implements the necessary methods for changing of safeness, and instances of the new class can be passed around just as easily and type independently.

In C++ it’s not so simple, so Grantlee needed another way. I started experimenting with a SafeString class as a subclass of QString. Preserving the safeness of an instance was not a large problem. Nor was overriding safeness-changing methods by using SafeString in the API instead of QString. However, the tricky part was passing SafeString instances around in QVariants without using QVariant::fromValue all the time.

There are some methods in the extension API where a method must be implemented to return a QVariant, possibly containing a SafeString. That should be as easy as simply returning an instance of the SafeString class, just like is possible with QString. The reason that works with QString is that QVariant has an implicit constructor which takes a QString. I couldn’t just add a new constructor to QVariant, so I created on SafeString an operator QVariant() which simply returns QVariant::fromValue(str);.

It worked quite well. Except that it only worked on gcc. Testing revealed that MSVC and Sun Studio were down-casting the SafeString to a QString and putting that in the QVariant, discarding the safe-ness information.

After discussing it with colleagues I tried out some other ideas such as inheriting privately from QString and making use of the using keyword to bring the QString methods public again. That didn’t work either. I got a compile error that instead of using operator QVariant, it was trying to cast up to QString and use that implicit constructor, but it was an inaccessible base class. Another idea was to create a QString wrapper class instead of a subclass. That got me most of the way there in that the operator QVariant() worked on all compilers, but I still had to implement forwarding for all QString operations.

The penultimate solution was to wrap a subclass of QString instead of QString directly. Initially the wrapped class was available through operator->() so that things like mySafeString->replace(); called the reimplemented method and returned a SafeString with the appropriate safe-ness attribute. A simple file was used to test the behavior of different compilers. Eventually though, the words of the wise were confirmed that that was abuse of operator->(), so now the NestedString in SafeString is available through .get(). That works quite well too. All QString methods which return a QString are reimplemented to return a SafeString and a few more overloads are added to make the use of SafeString quite transparent, so it’s mostly hidden in the documentation.

Grantlee Gems: Making the documentation correct

April 13, 2010

Doxygen creates API documentation with ease, but the output is not exactly what you want until you spend some time deciding what you want to include in the API docs, and getting a consistent appearance throughout.

In the Grantlee documentation, there are many references to tags like “{% for %}” and variables such as “{{ my_var }}”. Those should always appear in a typewriter font, and use non-breaking spaces so that the entire tag or filter is always on one line.

Instead of writing the necessary "<tt>{%&nbsp;for&nbsp;%}</tt>" each time, it makes sense to define some macros so that in doxygen comments a simple @gr_tag{for} can be used and doxygen replaces that with the correct, consistent content.

Another piece of Doxygen magix is the use of the following lines in the Doxyfile:

PREDEFINED             = Q_QDOC TemplateImpl:Template GRANTLEE_CORE_EXPORT=
EXPAND_AS_DEFINED      = TemplateImpl

Qt documentation uses the preprocessor with the Q_QDOC define to exclude content from the public API documentation. This can be useful to hide from the documentation API that is internal, but necessarily in public headers. Additionally, GRANTLEE_CORE_EXPORT is defined to nothing when creating docs so that it does not appear in the generated documentation.

The TemplateImpl helps the documentation lie to the user. I’m sure purists would let me know it’s a bad idea, but Grantlee::Template is actually a typedef for QSharedPointer<TemplateImpl>. Consumers of Grantlee should always use Template through operator->(), but the documentation should refer to Template, not TemplateImpl.

In the header file, the Q_QDOC macro substitutes Template for TemplateImpl:

#ifdef Q_QDOC
#define TemplateImpl Template
#else
typedef QSharedPointer<TemplateImpl> Template;
#endif

and the EXPAND_AS_DEFINED line tells Doxygen to “really substitute it”.

It is possible to customize the appearance of documentation generated by Doxygen by specifying custom header.html, footer.html etc files. Doxygen already uses Qt, although it’s an internal old version (Qt 2 perhaps?). If ported to Qt4, I could use Grantlee to change the appearance of the documentation. It’s all just part of the world domination plan…

Grantlee Gems: Creating documentation for Qt Assistant

April 12, 2010

One valuable feature of any software library is easily accessible documentation. Qt Assistant provides a good way to browse the Qt documentation.

For everyone else doxygen generates API documentation and can even generate documentation which can be used with Qt Assistant. Using a suitable doxytag file it is also possible for doxygen to create external links to the Qt documentation.

However, depending on where the documentation is accessed, the external links might have to be different. When the documentation is viewed on the internet, the external links should end on the online Qt documentation. When viewed in Qt Assistant though, links to Qt classes should open the correct link in the assistant, not an external web browser.

It turns out that by using qthelp://com.trolltech.qt/qdoc/ as the prefix for the links in Assistant, Qt references will be opened in the latest version of Qt in assistant. There is still a problem of using different links for the online documentation though.

The way I do this in Grantlee is to generate the documentation twice. Once with each target for the links. Two Doxyfiles are created for the two external link configurations using a Doxyfile.in cmake file as a template.

The configure_file CMake command is then used to create the two appropriate Doxyfiles. A nice benefit of doing it this way is that the version can also be injected into the Doxyfile, so the version of your library needs to be specified in only one place, the CMakeLists.txt file. There’s no need to also maintain a version number in the Doxyfile or the Mainpage.dox file.

configure_file only allows simple string substitution, not loops or conditionals. Sounds like I need to port CMake to Grantlee :).

Grantlee finally out the door

April 12, 2010

I’ve finally released Grantlee Gold v0.1.0. Some people thought it would never happen 🙂

Despite the low version number, it is already quite an advanced as I’ve written about over the last few months (almost year). It has taken a long time to actually finish the release, but I’ve learned tonnes along the way. It has been very useful to have a relatively small scale project to learn new APIs and tools I hadn’t used before.

Developing Grantlee made me a git user, taught me how to use CMake beyond CMakeLists.txt files, made me get a windows development environment up including MSVC and MinGW compilers, made me learn how to use QtScript, QMetaType, QSharedPointer and boost smart pointers, how to trick doxygen into creating complete but minimal documentation, how to use valgrind, how to write unit tests properly, what those MODULE_EXPORT macros in front of class names actually do, and much more.

I’ll be publishing a mini series of Grantlee Gems to disseminate some of that knowledge during the next few days.

Using Grantlee for code generation

April 6, 2010

Grantlee rustles on toward a release. I recently added one more example application showing the code generation opportunities it makes possible.

[blip.tv ?posts_id=3468342&dest=-1]
[OGG link]

In the video I edit and create some Qt Properties and methods with arguments in a simple UI, fill in some additional metadata, and then generate code representing the content of the dialog. The actual code is generated with some Grantlee templates. Simple loops are used to create the properties in the dialog, and if conditions for empty argument lists or the use of the pimpl idiom.

This could potentially be a time saver for generating the boring bits when creating a new class. Beyond that though, it is language independent. The structure and grammar of the generated code comes entirely from some template code files. The output language is entirely contained in the templates, and the Context of the rendering stage describes the content of the class. That means that it can also generate python code with the same Context and the same UI. There is a strong separation and encapsulation of language structure in the templates themselves.

Use of the Qt Resource system means that additional language templates could be added and distributed as external binary resources. So potentially someone could write and ship java templates long after the initial application was deployed.

I didn’t add that myself because if I let feature-creepism take hold in the example applications, there would never be a release of Grantlee. So back to that. 🙂

Unfortunately the video is quite jumpy, but if you want to try it out for yourself:

git clone git://gitorious.org/grantlee/grantlee.git
cd grantlee
mkdir build && cd build
cmake .. && make && make install
cd ../examples/codegen
mkdir build && cd build
cmake .. && make && ./codegen

So who wants to turn it into a QtCreator or KDevelop plugin? 🙂

Grantlee::RichTextBuilders

April 5, 2010

In my ongoing quest to get a Grantlee release out the door, I recently imported the KRichTextBuilders from kdepimlibs and renamed them Grantlee::RichTextBuilders.

I wrote those classes in 2008 but they were never used yet, and their headers were never installed. The reason for that is mainly that I was not happy with the API. The intention of the builders classes was to make it easier to create “cleaner” html from a QTextDocument that what is returned from QTextDocument::toHtml().

Users seem to have a lot of complaints about it taking more space than it needs to, but on a more relevant level, the toHtml call returns a html document complete with metadata such as a element which needs to be removed if data from multiple QTextDocuments is to be combined into one with an external theme, as is the case with KJots.

Up to now the way KJots has done that is to have an aggregation QTextDocument and do something like

  foreach( QTextDocument *page, book )
    aggregationDocument->insertHtml( page.toHtml() );

There is some other processing done to put things like breadcrumbs and table of contents into the aggregation document. That works, but it ties the content of the aggregation document into the C++ code, which is exactly what I want to avoid in the bright future with Grantlee. All of that stuff, including the placement and content of the table of contents, and even whether it should exist at all should be externalized to Grantlee themes. I recently wrote about that with screenshots on the dot.

Additionally, the toHtml() does not know what to create in the html output when it comes across the custom QTextObject you have inserted into your document.

Finally, maybe you don’t want to output html from your QTextDocument at all, but you want the contents output as MediaWiki markup or Markdown. What then?

The more flexible way to get the data out of a QTextDocument is then to iterate over the content of it, which is made up of QTextFrames and QTextBlocks.

That is exactly what the RichTextBuilders written back in 2008 do. I had just finished reading the GoF book (that is , Gang of Four 🙂 ) about design patterns, which has an example of exactly this problem, and so I used an interpretation of the Builder pattern to implement them.

QTextObjectInterface

The problem is that was not extensible in all the ways QTextDocument is. Custom objects may be inserted into a QTextDocument to do anything you want. For example, maybe you want to drop sound files into your notes application and get a nice widget for playing it. When you export the file to html you want the sound file to still be usable in the exported version. The way this is done in the application is to implement QTextObjectInterface, insert the custom object as a UnicodeReplacementCharacter with a specific QTextCharFormat, and that can be intercepted and drawn in a custom way later when laying out the document in a QTextEdit.

The problem is that adding that kind of functionality to the RichTextBuilders would require adding a new virtual function in the AbstractMarkupBuilder, and adding calls to that in the MarkupDirector. Adding new virtual functions is not really an option if binary compatibility is to be maintained. I realized though that the use of virtual inheritance would allow me to extend the Builder interface to output custom markup, and to implement the code in the MarkupDirector to handle the custom QTextObjects, or to handle custom QTextBlockUserData.

That is exactly what the textedit example in the Grantlee source does. The AbstractAudioBuilder interface defines an extra method for creating markup for representing audio. That interface is implemented by AudioTextHtmlBuilder, which also inherits the rest of Grantlee::TextHTMLMarkupBuilder, and by AudioPlainTextBuilder, which also inherits the rest of Grantlee::PlainTextMarkupBuilder. The Audio*Builder implementations really only implement support for creating output for representing audio. There is very strong separation of concerns. In turn, the AudioTextDocumentDirector is concerned only with extracting the audio information from the QTextDocument.

The entire process is also documented in the Handling Custom QTextObjects example.

The result is a text editing application which can play and export sounds. Maybe KJots 4.6 will have a feature like this.

QTextEdit on the left and QWebKit \"exported\" version on the right.

On the left is a QTextEdit whose content is editable and which supports a stylish play button, and on the right, a QWebKit element which supports the html5 element showing the exported version. Unfortunately, I get hangs with even trivial WebKit using apps, so I’ve put the text of the audio tag in the output instead of the actual tag because I can’t test it properly.

Of course it uses Phonon internally. KJots in trunk already uses Akonadi and Plasma, with more integration with Nepomuk, GHNS and now Phonon potentially in the future. Now all I need is an excuse to add a Marble dependency. KDE Pillars: Gotta catch ’em all.