KPovModeler Tutorial

Andreas Zehender zehender at kde.org
Sat Jul 12 16:15:52 CEST 2003


Hi Hugo!

As promised here the tutorial:

One of the best example for all following sections is the class PMBox. Maybe 
you should look at this class while reading the tutorial.

All POV-Ray objects are subclasses of the class PMObject. PMObject and 
PMComposite object implement the basic functionality for hierarchies of 
objects with references to siblings, children and parent objects.


Basic class attributes and information:
-----
There are two methods that provide basic class information:

1) PMObject::description( ): A translated description of the object
2) PMMetaObject* PMObject::metaObject( );

The class PMMetaObject holds all information about the class:
- The class name
- The class hierarchy (a pointer to the meta object of the parent class)
- A factory method to create a new instance, of the information that this 
class is an abstract class
- A list of properties, to get and set attributes by name

Undo redo information
-----
PMObject has a virtual method createMemento, that creates by default an 
instance of the PMMemento class. A memento holds all changed attributes of 
one owner object.

All set methods have this format
if( newValue != m_oldValue )
{
   if( m_pMemento )
      m_pMemento->addData( pointerToTheMetaObject, someID, m_oldValue );
   m_oldValue = newValue;
}

The combination <metaObject, ID> has to be unique and identifies the 
attribute. This way you don't have to know which IDs are used in base 
classes.


When an object has to be changed, for example by an object properties view, 
first PMObject::createMemento is called.
Then the objects attributes are changed. The old values of changed attributes 
are now stored in the memento.
Then the properties view takes the memento with PMObject::takeMemento and 
creates a PMDataChangeCommand for undo/redo.

If an old state should be restored, PMObject::restoreMemento is called.

PMBox::restoreMemento iterates over all stored values, ignores all values that 
have a pointer to another meta object (and therefore are values of other 
classes in the hierarchy) and restores all own attributes.
Then it calles restoreMemento for the base class.

Serialization
-----
All data is stored as xml. Loading and saving objects is quite simple with the 
Qt xml classes
Just look at PMBox::serialize and PMBox::readAttributes.

Representation in the properties view
-----
The class PMDialogEditBase is the base class for all widgets in the properties 
view. PMObject has a factory method PMObject::editWidget to create the 
correct edit widget.
There is a corresponding edit widget for (almost?) all objects.

PMDialogEditBase has these important methods:
1. createTopWidgets and createBottomWidgets.

These two methods specify the order in which widgets of all classes in the 
hierarchy are arranged.
createTopWidgets first calls the implementation of the base class and then 
creates widgets for the own attributes.
createBottomWidgets first creates widgets and then calls the implementation of 
the base class.

This leads to the followind order for PMBox:
topWidgets (PMObject)
topWidget (PMCompositeObject)
topWidget (PMNamedObject)
topWidget (PMSolidObject)
topWidget (PMGraphicalObject)
topWidgets (PMBox)
bottomWidgets (PMBox)
bottomWidgets (PMGrahicalObject)
bottomWidgets (PMSolidObject)
...

Edit widgets with important attributes that should be shown first create the 
edits in createTopWidgets (like the name attribute in PMNamedObjectEdit), 
objects with attributes that shouls be shown last create the widgets in 
createBottomWidgets (like the switches in PMCompositeObject).

This way every edit widget has automatically the widgets of the base class 
plus some own widgets.

2. displayObject
Displays the attributes of the current object

3. isDataValid
Validates the data and displays an error message if the user has typedin some 
invalid data.

4. saveData
Saves the attributes in the edit widget to the displayed object.

5. The signal dataChanged
This signal should be emitted when a value was changed in some widget. There 
are a number of widgets that implement this signal (PMIntEdit, PMFloatEdit, 
PMVectorEdit ...)


Graphical representation:
-----
The class PMViewStructure represents the wire frame of an object. It contains 
vertexes and connections and maybe later faces.

The view structure is create by PMObject::createViewStructure. This method is 
called when the object should be rendered in the wire frame view and the view 
structure is not up to date. To mark the view structure as invalid, call 
setViewStructureChanged in a set method that changes the view structure 
(PMBox::setCorner*)

To save memory, every class can have a default view structure that can be 
shared between different instances.

Imagine a user, that creates a number of boxes and resizes the boxes only with 
transformations and not with the corner attributes. Then all boxes have the 
same view structure, both vertexes and lines.

And even when the user changes the corner attributes, the information which 
vertexes are connected to each other can be shared, as it is the same for all 
boxes.

PMObject::defaultViewStructure returns the default view structure, if any 
exists. This view structure is automatically used if PMObject::isDefault 
returns true.

In PMBox::createViewStructure you can see, how the line information is shared.

The class PMControlPoint represents a control point in the wire frame. With 
control points the user can change object attributes in the wire frame view. 
There is one control point class for every type or behavior of control 
points.

PMObject::controlPoints creates the control points for the object

PMObject::controlPointsChanged take the control point attibutes to synchronize 
them with the objects attributes.

Object hierarchies
-----
There is a rule based system (PMInsertRuleSystem) that determines which object 
can be inserted into another object at which position.

The rules are described in baseinsertrules.xml.
There is a dtd with some basic description of the tags.

I think the tags are self-explanatory.

POV-Ray IO
-----
POV-Ray output is located in PMPovray31Format and pmpovray31serialization.*

The serialization methods use a class named PMOutputDevice that handles 
indentation.

The important methods are
objectBegin
writeLine
objectEnd

The scanner and parser is maybe a bit difficult to understand. Just look at 
some parse methods for different objects.

So far the basic tutorial.

If you have questions, just ask here on the list.

Andreas

-- 
--------------------------------------------------
 Andreas Zehender
 Master of Computer Science, Dipl. Ing. (BA)
 http://www.azweb.de
 az at azweb.de | zehender at kde.org      
--------------------------------------------------



More information about the kpovmodeler-devel mailing list