Calligra Sheets Development Notes

Maintainer: Ariya Hidayat (ariya@kde.org)

Some portions by Tomas Mecir (mecirt@gmail.com)

Revision: September 2004.

Introduction

This document contains information about internal structure of Calligra Sheets as well as some notes of upcoming redesign. The sources for this document are mainly the discussions which take place in calligra-devel mailing-list and the source code itself.

Manipulators

Status: OUTDATED.

Currently, every operation on a cell or on a range of cells is quite complex. You need to ensure correct repainting, recalculation, iterate on a range and so on.

To address this issue, manipulators shall be implemented. A manipulator will implement one operation (formatting change, sequence fill, ..., ...).

Basically, usage of a manipulator should look like this:

Manipulator *manip = manipulatorManager::self()->getManip ("seqfill");
manip->setArgument ("type", 1);
... (more setArgument's)
manip->exec (selection);

That's all...

What concerns manipulator implementation, you'll derive from the base manipulator and reimplement constructor and methods initialize() (called just before the operation starts), processCell(), and maybe done(). The constructor or initialize() would set some properties for the cell-walking algorithm, and then it won't care about it anymore. The base class will walk the range and call processCell() for each cell, possibly creating it if it doesn't exist (if the manipulator wants so).There will also be some methods that can be used to process the whole range or row/column at once, if the manipulator wants to do so (useful for, say, formatting manipulators that will be able to set attributes of a whole range or row/col, in accordance with thoughts about format storage below.

In addition, the manipulator can implement the undo/redo functionality - the base manipulator will provide some common stuff needed to accomplish this.

Selection handling

Status: OUTDATED.

The selection shall be an instance of some RangeList class, or however we want to call it - this will contain a list of cells/ranges/rows/whatever - like current selection, but will contain more entries. This will allow easy implementation of CTRL-selections and so, because thanks to manipulators, each operation will automatically support these.

Repaint Triggering

Status: OUTDATED.

As mentioned above, the interface between the core and the GUI needs to be kept at minimum. Also, the number of repaints needs to be as low as possible, and repaints should be groupped whenever possible. To achieve all this, the following approach can be used:

When a cell is changed, it calls some method in KSpread::Sheet - valueChanged() or formattingChanged(). These methods then trigger everything necessary, like a call to the painting routine or dependency calculation.

This simple system would work on itself, but it would be slow. If you do a sequence fill on A1:A1000 and you have a SUM(A1:A1000) somewhere, why would you want to compute that SUM 1000 times, when you can simply compute it after the sequence fill has been finished? Hence, the sheet will offer some more methods - disableUpdates(), enableUpdates(), rangeListChanged() and rangeListFormattingChanged(). All these will be used (solely?) by manipulators, preferably by the base manipulator class, so that we don't have to call these functions in each operation. After a call to disableUpdates(), there will be no repainting and no dependency calculation. Note that a call to enableUpdates() won't cause any repaints either, as the sheet cannot remember all the calls (due to loss of range information). Hence, the base manipulator class needs to call the correct rangeList*Changed method to trigger an update in an effective way. The base manipulator needs to be configurable by the manipulators that derive from it, so that it knows whether it changed cell's content or formatting.

Value

Status: FINISHED.

to be written.

Commands Based on KCommand

Status: OUTDATED.

Until lately, to implement undo and redo, Calligra Sheets creates corresponding KSpreadUndo classes for each action and runs them when the user undoes those actions. KSpreadUndo also has redo function whose job is to redo again the action after being undone.

All this needs to be converted to manipulators - these will be KCommand, hence we should be able to undo/redo every operation (provided that the corresponding manipulator provides methods to store/recall the undo information).

Cell Storage

Status: FINISHED.

to be written.