Internals of Styles in Calligra
This page is about how styles are handled internally in Calligra. As you can read in the parent page, there are two ways that styles are handled in Calligra now:
- The old way where everything is kept inside each shape and no styling information is saved in style classes. This applies also to named styles, which is the big problem. In other words, the named styles are not kept.
- The new way where styling information is kept in style classes and can be saved back later. This is only applicable to named styles, of course, since the automatic styles are always generated while saving using the KoGenstyle class.
I also want to propose an even more improved system for styles that builds on and extends the new way. See below for details about this.
Most of the style handling are done in 3 libraries under libs/ :
/libs/odf contains classes that are relevant for handling ODF files. Fundamental classes for loading and saving are here: KoXmlReader and KoXmlWriter, KoGenStyle and KoGenStyles, KoOdfReadStore and KoOdfWriteStore.
There are also a number of pure data store classes that store specific types of medium level data like KoBorder (border information for paragraphs, pages, cells, etc), KoStroke (information about pen strokes), KoElementReference (unique identifiers to elements in a document) and so on.
There seem to also be a number of classes that duplicate classes under libs/kotext: KoCell, KoCellStyle, KoColumn, KoColumnStyle, etc, which seem to have to do with tables. I have not yet investigated where these are used and if they in fact do duplicate the classes in libs/kotext.
The old way
In the old way there are no special classes that store the style information. Most of the style information is read into and kept inside the classes that use them. The most prominent example of this is the KoShape class in libs/flake which is the base class for all shape implementations.
KoShape has a method called loadOdfProperties() which load all or a subset of the shape's graphic properties from the style stack. This method examines the graphic-properties of the styles that are on the style stack including the one whose name is in the style-name property of the shape itself. It does this by calling a method loadStyle() which loads the style. If you want to load properties that are only relevant for a specific type of shape, then reimplement loadStyle() in that shape and call KoShape::loadStyle() at the beginning of it.
Loading of shape information is done using the loadOdf() method, which normally calls loadOdfProperties() somewhere near the top. A parameter to this method is the so called KoShapeLoadingContext which contains a number of relevant data that is used during the loading. One of them is the KoOdfStylesReader which originally comes from the KoOdfReadStore which represents the zip store of the ODF file.
The styles reader gives you the KoXmlElement which contains the XML tree for a certain style. It is then up to you to examine the properties of the style or push it on the style stack and examine that instead. This means that for every object that uses a style, the XML text of the style is reparsed. Also if the datatypes of the properties are complex, like vectors, matrixes, paths or other advanced data types, then they have to be reparsed from the string value of the property in question.
This is very inefficient but it is how most of the styling works right now.