Multithreading in KOffice

One of the things we wanted to do in KOffice is to use Krita when printing images from KWord. The reason for this are a couple, but the most important being that we want to have just one way to do printing of images and not waste time maintaining a more than one.
Naturally the option to let Krita convert the images to CMYK while printing (as soon as QPrinter supports that) sounds like a nice to have as well.

It turned out to be a bit harder than I first thought. The reason for that is due to the way that Flake works is that is separates processing and painting. The painting is reused for printing and painting always has to be as fast as possible; so no expensive calculations there. This keeps the interface snappy and user friendly. And I know you want that.

So, the problem is thus that painting is designed to paint the stuff we can paint right now; even if thats not the full content. The top couple of paragraphs of text, for example. And when the rest of the paragraphs have been properly layouted, then we'll just paint again. This concept works great on screen, but breaks down when printing. We don't want partial text on paper, we should wait until the whole text is positioned.

This effectively means we need someone to monitor the progress of a flake-shape and when its done with all the processing we can start painting. And this quickly means we need to do multithreading.

For that reason I added a KoShape::waitUntilReady() virtual method that a flake-plugin should implement if it has the problem that it can paint partial data. The idea there is that I call that method while trying to paint, and the method doesn't return until the shape is fully ready. After which I paint it to a printer. I implemented this for both the text shape and the krita-flake shape.

KWord now starts printing in a new thread and checks the quality of the images, loading the Krita shape plugin when it needs to. It will then drop back to the main-thread to actually do the painting of the shape (so shape-authors don't have to worry about multi-threading and locking). And it repeats this for each page.

It prints just great (and correct too!); while keeping the user interface snappy and responsive.

By now I wrote a nice collection of useful tools for multi-threading for KOffice. There is a KoAction which is the simplest interface you can use to make code run in different threads. There is a KoProgressUpdater which is a helper class to update progress of a task on a QProgressBar, from any number of threads. Naturally the new KoPrintingDialog this post was about. And we now have a KoShape::deleteLater() which is a thread-safe deletion of the shape. Required so we don't delete a shape that's just being painted in another thread, which would cause a crash.

Flake now doesn't just rock for easy painting and editing, it also is great for multithreaded applications and professional printing.