OK, I suspected this what what you are referring to.
"Roles" as they are used in the Qt Model / View framework are simply a set of flags that are used to indicate which specific value is being asked for in a call to a model method. See the documentation of Qt::ItemDataRole for the list.
In your Python example, the role that is passed in is evaluated in a set of if / elif conditionals; in C++ this is typically done in a switch statement:
switch( role )
{
case Qt::DisplayRole:
retVal
= QString( "Here is the text I want to display" );
break;
case Qt::DecorationRole:
retVal
= QIcon( "myIcon.png" );
break;
// ...
}
return retVal;
QVariant retVal;
switch( role )
{
case Qt::DisplayRole:
retVal = QString( "Here is the text I want to display" );
break;
case Qt::DecorationRole:
retVal = QIcon( "myIcon.png" );
break;
// ...
}
return retVal;
To copy to clipboard, switch view to plain text mode
Whenever your (or a standard Qt model's) implementation of the data() method wants the model to do whatever is the default for a given role, it returns an empty QVariant. So, if I don't define tool tips for my custom model, then I return QVariant() when asked for Qt:: ToolTipRole. The default behavior in this case is to not display a tool tip.
For Qt:: DisplayRole you will return a QString (inside of a QVariant) that contains the text you want displayed in whatever view element (cell, row, list item, etc.) is displaying the content of that particular QModelIndex in the model. FontRole lets you return a QFont that specifies how the text is formatted. If you return an empty QVariant for this role, then the view's default font is used. Likewise, ForegroundRole lets you specify the text color, BackgroundRole lets you specify the background color behind the text.
In any case where you want the default behavior to occur, you simply return an empty QVariant. If you do this for DisplayRole, then you get an empty cell in your table, the same as if you had passed back an empty QString since the default behavior is to display nothing. ForegroundRole applies the default text color, BackgroundRole applies whatever color the whole view uses as a background.
This same set of ItemDataRole values is used in the setData() method, this time to change what is held in the model.
There is a special set of role values starting with 0X0100 (Qt:: UserRole) that lets you define your own roles. These are usually used with a custom view class that understands those roles (your generic Qt views don't know anything about UserRole values).
An example of using custom UserRole values: I have a table-based model that I display in a table view. There, I am mostly concerned with the DisplayRole, ForegroundRole, and BackgroundRole. The table view doesn't know anything about the custom UserRoles I have defined.
However, I also use the same table model to construct x-y scatter plots. In this case, the plot is told to select "x" data from some column (say column 3) in the table model, and "y" data from a different column. I could have the plot view ask for the DisplayRole for each of these, in which case it would get a formatted QString that it would then have to turn back into a number to give an x or y coordinate. Instead, I added a custom role with the value UserRole + 1, that returns a QVariant wrapping a floating point value. The plot view asks for this role when requesting the x or y coordinate. My plots also have the ability to vary the size of the dots, so for that there is another UserRole type (UserRole + 2) that returns the dot size. Another UserRole + 3 gives me the ability to define a custom marker for each point in the plot, and so on.
Qt could have implemented an alternative. Instead of a data() method that takes a Qt: ItemDataRole flag, it could have implemented a dozen or more separate methods: one named displayData(), one named iconData(), and so forth, that only took the QModelIndex as an argument. While this would work for the standard roles, it wouldn't work all that well for custom UserRole values because you can define any number of them in a custom model. It also leads to "interface bloat" - lots of little class methods where just one would do.
But, I don't fully understand what is happening in the "data" method when the role is DisplayRole (I didn't change that part of the elif, it came with the example. (Why does the DisplayRole return code return empty QVariants?)
In your particular example, the logic is as follows:
- if the index refers to an invalid (row, column) combination, then an empty QVariant is returned. Invalid indexes are used frequently for various reason and contain (-1, -1) as coordinates.
- if the role is BackgroundColorRole (which is obsolete, by the way), it returns a color if column 7 of the row contains the word "Stage"
- if the role is anything else -except- DisplayRole, it returns an empty QVariant and the view does whatever it does by default
- if the role is DisplayRole, it returns whatever is in the position (row, column) of the data array that underlies the custom model. Python coerces this into a displayable string in the case where it isn't a string to begin with. As you know, Python collections can contain a mixed bag of any data type, so element (0,0) might contain 1, (0,1) contains 3.14159, and (0,2) contains "Bananas". So the return values in these three cases would be strings: "1", "3.14159" and "Bananas", suitable for display in a table view.
Bookmarks