Custom Model for TableView or QStandardItemModel - qt

I want to create a TableView with two columns:
The first one for a parameter name
The second one with the parameter value, which could be a float, bool, int or a string
The second column should be editable, and a bool should be represented by a checkbox. For this model, should I subclass QAbstractItemModel or would the QStandardItemModel be fitting? Also, should one item have the two properties name and value, or should this be better seperated into two items?

It depends on your subject field. If you have big number of parameters then you should subclass QAbstractItemModel, because in the other case time of data view will be significant, if not QStandardItemModel is quite simple for this purpose.

Related

Get Item from QStandardItemModel for QTableView

I have a QTreeView in which each node represents a data object. I managed to pack a pointer to this data objects into a QVariant so that I know which is selected in the Tree. I can access the nodes by the currentIndex() function.
The root of the Tree is at QStandardItemModel::invisibleRootItem(). Other nodes are added by the parent nodes appendRow function. So the Items have no row and column that I can use in QStandardItemModel::item().
Is there a way to give the nodes valid coordinates or to retrieve the items without coordinates.
In QStandardItemModel, there is a item(int row, int column = 0) method. Qt nomenclature doesn't use 'get' as prefix of getters methods.

How do I Insert an item at top of QTreeView

In my app I'd like to insert an item at the top of a QTreeView.
What I have so far will insert an item just above the currently selected item. The code (nicked, I think, from the EditableTreeviewDemo):
QModelIndex index = this->selectionModel()->currentIndex();
QAbstractItemModel *model = this->model();
if (!model->insertRow(index.row(), index.parent()))
return;
I guess what I need is the index to the current first row? How do I get this?
As a side question, what happens to the current index when a row is inserted? Does it continue to point to the same item, or the same row?
Well first you have to know that insertRow is a function from QAbstractItemModel and it will call insertRows (with an s). This function must be redefined in your model subclass if you want to allow insertion of data in your model.
http://doc.qt.io/qt-5/qabstractitemmodel.html#insertRows
Also consider that any parent of a topmost index is a invalid QModelIndex. Then the call to do would be :
model->insertRow(0, QModelIndex());
And because this is the default value for the second parameter, simply call :
model->insertRow(0);
Then in your redefinition of insertRows simply check the validity of you parent index to ensure you news underlying data is created where you want it to be.
For you question, inserting data in the model won't affect the current and selected items.

Qt QListView with different delegates per column

The Delegate system is not clear to me by now.
I have a QListView properly displaying my custom model.
My model is composed by the following columns:
Column 1, 2 and 3 are a Text column, the column's item's text is filled using QAbstractItem::setText();
Column 4, 5, 6 and 7 are a QVariant of a custom class. These column have items filled with QAbstractItem::setData(QVariant::fromValue(MyCustomClass());
What I need from the QListView is it to display the text on the column 1,2 and 3, and display a custom QString obtained by a method of MyCustomClass on clumns 4,5,6 and 7.
How can I achieve that?
Use QAbstractItemView::setItemDelegateForColumn(int column, QAbstractItemDelegate* delegate), docs.
Have you got a custom model? If all you are pulling out of your custom data is text, it would be easier to reimplement QAbstractItemModel::data(const QModelIndex& index, int role) const, query which column index is, and if it is your custom data column return the display role with the custom data text; otherwise just call the parent implementation.

Different Qt::CheckStateRole for different views?

Currently I have a simple setup where I maintain a list of bools corresponding to each item in my ListModel:
http://programmingexamples.net/wiki/Qt/ModelView/StringListModelCheckable
However, now what I want to do is have two such lists bools, say IsHot and IsLarge. Then I want to have a ListView that displays each string with a checkbox for one of the bools (the "Hot" view), and a separate ListView that displays each string with a checkbox for the other bool (the "Large" bool). Any hints on how to go about this?
Make your model a table, return the data in two different columns, the cells in these columns will be checkable.
On your list views, call QListView::setModelColumn to set the column the list view displays.
If you want to synchronise scrolling between the lists, you would then be better using a QTableView, so that rows would match up.
Edit to add more detail on returning text and check state.
To return a text and the state of a checkbox from the model you return different data for different roles from the [data] function on your model.
From the manual for Qt::ItemDataRole:
Qt::DisplayRole The key data to be rendered in the form of text. (QString)
Qt::CheckStateRole This role is used to obtain the checked state of an item. (Qt::CheckState)
Both columns in your model would return the same data (the name) for DisplayRole but different data for CheckStateRole

Programmatically adding a new row to a QAbstractListModel subclass

Within an already-instantiated QAbstractListModel subclass, how do I add a row with data in each column, and have the associated QListView display the new row?
It seems that the only way to do it is to reimplement insertRow and setData within my model, and then hack them together in some sort of sequence within another function to add a row. Must I do this? Surely Qt must make it easier to add a new row.
Thanks much!
--Dany.
Just change your model's data storage, in between beginInsertRows() and endInsertRows().
For instance, let's say you have a flat list model and your model stores the data internally in a QVector m_data. You want to prepend the list, i.e. insert a row at position 0:
beginInsertRows( QModelIndex(), 0, 0 ); //notify views and proxy models that a line will be inserted
m_data.prepend( somedata ); // do the modification to the model data
endInsertRows(); //finish insertion, notify views/models
I'm afraid you have to do it that way. From the docs:
Models that provide interfaces to resizable list-like data structures can provide implementations of insertRows() and removeRows().

Resources