GUI model

The result of the refactoring can be seen here: Refactoring GUI Model

This page contains collection of requirements for forthcoming refactoring in SessionModel and Parameterized item. The idea is to get rid from Qt property machinery completely and have items and their properties represented by uniform tree structure relying on QAbstractModel/QModelIndex machinery.

ParameterizedItem + property -> ComponentItem(?, SessionItem, etc)

We assume that everything will be derived from ComponentItem.

ComponentItem contains:
  • modelType: used to create items via ItemFactory (based member QString)
  • displayName: used to show an item in PropertyEditor, TreeView etc (QVariant or QString?)
  • valueOfItem: the value of Item (based on member QVariant)
Layer
|-- Thickness -- 5.0
|-- Position  -- (1.0, 2.0, 2.0)
    |-- X -- 1.0
    |-- Y -- 2.0
    |-- Z -- 2.0

Here, Layer is a ComponentItem of LayerType, with display name "Layer", without valueOfItem (invalid QVariant). The model sees it as a parent with rowCount=2 and columnCount=2.

Layer has two children. "Thickness" is a ComponentItem of DoubleType with display name "Thickness" and valueOfItem = QVariant(double).
The model sees it as a parent with rowCount=0 and columnCount=0.

The "Position" is a ComponentItem of VectorType with display name "Position" and valueOfItem = QVariant(QString) (or invalid QVariant?). The model sees it as a parent with rowCount=3 and columnCount=2. It has 3 children each of type DoubleType.

ComponentItem's valueOfItem

  • QVariant(double), QVariant(int), QVariant(QString), QVariant(bool)
  • QVariant(QStringList) or QVariant(ComboProperty) ?
How to do this?
  • QVarant is stored on board of ComponentItem, ComponentModel::data() returns ComponentItem::dataFunction(). The later dataFunction either returns valueOfItem QVaraint, or, in special cases, generated label, as in
    |-- Position  -- (1.0, 2.0, 2.0)
    

ComponentItem's attributes

Appearance
  • VISIBLE/HIDDEN, ComponentItem doesn't appear in PropertyEditor

Would be nice to make ComponentModel to respect this attribute. When HIDDEN is set, item and its children doesn't show up in QTreeView.

  • READONLY, editing of valurOfItem is disabled
  • DISABLED, item (both, displayName and valueOfItem) appears in editors in gray color, editing is not possible.

It is desirable to be able to set this parameters through ComponentItem itself. As a result of it, the model should notify all views.

  • How to combine ComponentItem's Appearance attribute with Qt::ItemDataRole ?
Attribute of double
  • AttLimits: min, max
  • Number of digits

Ideally, it should be possible to change number of digits somewhere for certain ComponentItem. For example, using wants to type alpha_f in better precision, than default 2 digits.

Tooltips
  • Should be possible to assign tooltip in ComponentItem's constructor.
  • Should be possible to redefine tooltip later, so the model get informed.
  • SelectorItem should have separate tooltips for all items in QComboBox

The current way of assigning property attributes seems to be reasonable

registerProperty(P_X, 0.0).setToolTip("bla").setHidden();

Signaling

We have decided that all signaling will go through the model. Additional Mapper will take care about informing specific views.
See collection of use cases below.

Unddo/Redo (low priority)

Possibility to make unddo/redo while adding/removing items to the model.

Serialization

We should be able to read/write model from/to xml files.

Backward compatibility of project files (important)

  • Possibility to provide partial load of older project files.

Here I mean not our previous-current situation (subItems-project-files we are not going to recover), but what will come after this big refactoring.

  • If certain property existed in old file, and is absent in new one, user has to be notified (property name, item name)
  • If certain item absent in old project file, but is required to be in new one, default item should be created, user has to be notified.

Item access, Inserting

QModelIndex SessionModel::insertNewItem(ModelType, parentIndex)
QModelIndex SessionModel::indexForItem(item);
item SesionModel::itemForIndex(index);

Moving, copying, (through xml machinery)

    ParameterizedItem *moveParameterizedItem(item, new_parent, row);
    ParameterizedItem *copyParameterizedItem(const item, new_parent, row);

Cloning

SessionModel::clone()
ParameterizedItem::clone()

PORT_0, PORT_1 machinery replacement

  • Some items can have only one children of certain type.

Currently, if in SampleDesigner somebody adds second InterferenceFunction to ParticleLayout, the SessionModel automatically removes previous one.

  • Some item can have only two items of certain type, but they are assigned to different PORT

CoreShellItem should have CoreParticle and ShellParticle. They are added by the user in arbitrary order, so we don't know which row contain which particle. So we have invented PORT to be able to distinguish.

Various cases related to the notifications.

They all appear in implementations of

    virtual void insertChildItem(int row, ParameterizedItem *item);

signals:
    void propertyChanged(const QString &propertyName);
    void subItemChanged(const QString &propertyName);
    void subItemPropertyChanged(const QString &property_group, const QString &property_name);
    void siblingsChanged();

protected slots:
    virtual void onSubItemChanged(const QString &propertyName);
    virtual void onSubItemPropertyChanged(const QString &property_group,
                                          const QString &property_name);
    virtual void onSiblingsChanged();

  • Mostly ParameterizedItem wants to know, if some of own registeredProperty has changed, to adjust own other properties/attributes.
  • But sometimes it wants to know about children or even grand children.