[scribus-dev] Some notes/questions about Scribus internals and my project

Elvis Stansvik elvstone at gmail.com
Sun May 22 12:30:16 UTC 2011


Hi all,

Today I took some time and did some browsing of the Scribus source to
try to figure out how it all fits together. Below are some notes I've
taken on some of the classes, mostly for my own sake.

Would be nice if someone could read through it and correct me if I got
something wrong. After that follows a rough plan for the first two
weeks of my project. Finally, there's a couple of specific questions
that have popped up. I'll have more questions, but these two are most
pressing right now as the project start is getting closer.

Best regards,
Elvis

Central Classes
-----------------------------
These are notes on (a few of) the central classes of Scribus. I've
excluded the styles system as it has kind of OK documentation in
styles/overview.txt.

ScribusDoc
---------------
Self-explanatory. Represents a document in Scribus. Some
responsibilities seems to be:

- get a list of objects in the document.
- get the current selection.
- manage styles and colors.
- manage grid and guides.

ScribusView
----------------
Central zoomable scrollarea showing a document. Its primary
responsibility seems to be to provide a UI for scrolling and zooming
(naturally).

PageItem and its subclasses
-------------------------------------
PageItem is the base class for all items. The base class seems to be a
bit intertwined with its subclasses, and can be queried for and
converted to its subclass type using is*() and as*() methods,
respectively (e.g. isArc(), asArc()). Page items have many
responsibilities, but most important for me seems to be that they draw
themselves to the canvas in their DrawObj_Item() method.

UndoManager
------------------
Central singleton class of the undo/redo system. Manages a map of undo
stacks, one for each document. I'm not 100% sure how the undo system
works as it does not seem to use the traditional command pattern for
undo/redo. But I understand that the undo stacks are stacks of
UndoState:s, and that multiple UndoStates can be packed into a
transaction which can be commited or rolled back. I wonder why it was
made into a singleton with several stacks (one per doc) instead of
having one undo manager per document? Also, even though it is a
singleton, pointers to the undo manager still seems to be kept in
classes such as ScribusView and ScribusMainWindow. But I guess this is
just for convenience?

General Notes
-------------------
Many of the classes such as ScribusDoc, ScribusView and PageItem have
a huge number of public member variables, many of them undocumented,
which users (and subclasses) of the classes rely on, and it's a bit
hard to tell what the responsibilities of each class really is. But I
think I have a somewhat OK view of it now.

CanvasMode
-----------------
Different modes of operations on the canvas seems to be implemented in
classes inheriting from CanvasMode. As an example, there is a canvas
mode for editing a polygon, editing a spiral et.c.

At a even higher level there seems to be the concept of "application
modes" (e.g. ScribusMainWindow::setAppMode(int)), which I'm not quite
sure what they are. Are they the same as canvas modes? In any case,
setting the "app mode" using ScribusMainWindow::setAppMode(int) seems
to be what results in a canvas mode change.

Notes on Painting of Items
-----------------------------------
Painting seems to be done in two places. The on-canvas painting of
items seems to be done by items themselves in their DrawObj_Item()
(and DrawObj_Decoration()) method. Painting of items for print output
seems to be done in the respective drawItem_*() methods in
ScPageOutput.


Now on to more specifics regarding my project. Below is a rough plan
for the first two weeks.

Week 1 - Prototype
------------------------
Begin creating a first basic PageItem_Table that has the traditional
basic table API. Something like (preliminary):

public:
  qreal width() const;
  qreal height() const;

  int rows () const;
  int columns () const;

  void insertRows(int index, int rows);
  void removeRows(int index, int rows);
  QList<qreal> &rowHeights() const;
  void setRowHeights(const QList<qreal> &rowHeights);

  void insertColumns(int index, int columns);
  void removeColumns(int index, int columns);
  QList<qreal> &columnWidths() const;
  void setColumnWidths(const QList<qreal> &columnWidths);

  void mergeCells(int row, int column, int numRows, int numCols);
  void splitCell(int row, int column, int numRows, int numCols);

private:
  /// Returns rectangle available for cell content.
  QRectF cellContentRect(int row, int column) const;

Note that the width/height API above refers to the dimensions of the
table itself, not to the table frame. The dimensions of the table
frame itself will be taken care of just like for other items.

The user should be able to insert the table the same way as current
tables are inserted. The table will not support any content yet, and
it will not use a style to draw itself but hard code cell/table
border/background.

Week 2 - Resizing of rows / columns / table
-------------------------------------------------------
Finish off the above, then add support for resizing rows, columns and
the entire table by implementing a new canvas mode.

Specific Questions
------------------------
1) Since painting of items is done in two places, in the
DrawObj_Item() method of the item itself and in ScPageOutput, does
this mean I'll have to write the painting code twice?
2) How does the current undo/redo system work? How do I implement
undoable actions? Will I need to implement one (or several?) new
UndoState classes?



More information about the scribus-dev mailing list