PDA

View Full Version : Model-view: Display items in different ways



taboom
12th August 2007, 13:07
I use the Model/View architecture for creating a tree-based structure. The model consists of nodes which can be of several different types.

The tree can look like this:
Root (type a)
child1 (type a)
child2 (type b)
child3 (type a)

Now what I want is to present type a and type b in different ways, say a is supposed to be a circle and b a rectangle.

What is the "correct" way for doing this?


I was thinking about using item roles to define the types. Say type a nodes respond that they are of "a" type when the TypeRole is fetched via the data()-function. Drawing then depends on this role's role, or data. That is, the data()-function for the TypeRole returns a new role that then defines how to draw the node.

Example:


// We have this in the model
QModelIndex root = model()->index(0,0,0);
QModelIndex child1 = model()->index(0,0,root);
QModelIndex child2 = model()->index(1,0,root);
QModelIndex child3 = model()->index(2,0,root);

// Getting the Type is via
int TypeRole = 34; //Available ItemDataRole

// Types are
int rootType = root.data(TypeRole);
int child1Type = child1.data(TypeRole);
int child2Type = child2.data(TypeRole);
int child3Type = child3.data(TypeRole);
// rootType == child1Type = child3Type == TYPE_A
// rootType != child2Type == TYPE_B


// How I thought of doing this is:

// Go through nodes and draw them
int childCount = model()->rowCount(index);
for ( int childNum=0; childNum < childCount; childNum++)
{
// Get the child and draw it
QModelIndex child = model()->index( childNum, 0, root );
// Get the type
int type = child.data( TypeRole );
//Draw them depending on the type
switch (type)
{
case (TYPE_A):
drawTypeA(child); //Draws the rectangle
break;
case (TYPE_B):
drawTypeB(child); //Draws the circle
break;
}
}


Is this how this is "supposed" to be done, or should the roles instead be directly used, so that drawing draws something only if the node is of correct type?


//We have several ItemDataRoles defined
int TypeARole = 34;
int TypeBRole = 35;

drawNode( child.data( TypeARole ) ); //Draws a rectangle, but only for A-type nodes
drawNode( child.data( TypeBRole ) ); //Draws a circle but only for B-type nodes



Or are there other better alternatives?

travlr
12th August 2007, 16:32
[/code]Is this how this is &quot;supposed&quot; to be done, or should the roles instead be directly used, so that drawing draws something only if the node is of correct type?


//We have several ItemDataRoles defined
int TypeARole = 34;
int TypeBRole = 35;

drawNode( child.data( TypeARole ) ); //Draws a rectangle, but only for A-type nodes
drawNode( child.data( TypeBRole ) ); //Draws a circle but only for B-type nodes

Or are there other better alternatives?

I'm guessing that this last piece of code is part of a custom view and not somehow part of the model...

I think your on the right track with your primary description of discriminating in the data() method. The only minor thing I do differently is contain the "type" in my item node instead of a custom role. Just a personal preference.

Mind you, I'm not an expert yet though. -travlr

wysota
13th August 2007, 09:27
The correct way is to implement a custom delegate (subclass of QAbstractItemDelegate or QItemDelegate) that will be able to determine if a particular index if of type A or B and handle the item accordingly.

taboom
13th August 2007, 20:05
Ok, I guess this was what I was looking for :) Thanks!