0

Quick question

Is there an easy/quick way to map a QListWidget or QStandardItemModel (for QListView) item to my application logic?

Complete Question

Note: I will use undistinctly both QListWidget or QListView and itsQStandardItemModel. From my current point of view for this question, switching from one to another is trivial.

I face usually the need to have a QListView or equivalent in an HMI, which shows some text value and need to react on selection/click.

In the SLOT, in order to perform the required action, the row need to be identified. Qt::DisplayRole is NOT appropriate because some texts could be duplicated and QStrings are not the best way to identify data in Computer Science.

// Click on a row
connect( &myView, &QListView::clicked, 
[&myView, this]( const QModelIndex &idx)
{
    // E.G. need to update the database for this row.  Which row?
});

Possible solutions:

  • Maintain a map to retrieve the ID from the QModelIndex row.
  • Save in the model row any ID, making easy to apply any operation.

First option is tedious: it requires to connect the model for keeping the map and the model synchronized.. Same logic again and again.

Second option seem by far the best: I save the (e.g. database id) and use it afterward; But, QListView model (up to what I know) does NOT include this very friendly and useful ID. So until now I had extended again and again the models for QListView.

How to map the QModelIndex back to my application logic? Do I really have to extend the model for that simple operation?

RELATED QUESTION: QTreeView: maintaining mapping between QModelIndex and underlying data

Community
  • 1
  • 1
Adrian Maire
  • 14,354
  • 9
  • 45
  • 85

1 Answers1

1

What about creating the QAbstractModel manually, this way you have complete control how the QModelIndexes are created, and you can use that to do stuff.

I'v implemented thousands of Qt Models, and I have never liked the QStandardItemModel approach as I would usually need to write more boilerplate than if I had come with the model myself.

  • Inherit from your QAbstractList/Table/TreeModel
  • implement index()
  • create a method for direct item access

.

// Click on a row
connect( &myView, &QListView::clicked, 
[&myView, this]( const QModelIndex &idx)
{
   auto& myItem = idx.model()->directAccess(idx.row());
});
  • profit.
Tomaz Canabrava
  • 2,320
  • 15
  • 20
  • Yes, that is what I am doing ("So until now I had extended again and again the models for QListView"). I wonder if there is a predefined `role`, some hidden behavior or whatever else that avoid me to implement this QAbstractItemModel, so I could re-use all the normal QStandardItemModel stuff. – Adrian Maire Apr 12 '17 at 11:41
  • I created a QObjectListModel that holds a QList and I'm using it everywhere, using the Q_PROPERTIES to populate things on the table (one column per peroperty). – Tomaz Canabrava Apr 12 '17 at 11:48
  • Absolutely, if there is no easier way, I will have to create/maintain a Model with similar behavior. Probably some template model, so the content is easy to set. – Adrian Maire Apr 12 '17 at 11:52
  • 1
    template wont work - it's a QObject after all. moc needs to run on it. I would go for a QVariantModel or a QObjectModel, it's easy to deal with QObject pointers. – Tomaz Canabrava Apr 12 '17 at 11:54
  • Mmm, templates seem to works pretty fine, QAbstractItemModel is not a QObject. Or did you meant the QListView? – Adrian Maire Apr 12 '17 at 13:33
  • QAbstractItemModel inhertits from QObject, for sure. – Tomaz Canabrava Apr 12 '17 at 14:25
  • so what is the issue with templating QAbstractItemModel? I just did it and up to now it seem to works. – Adrian Maire Apr 12 '17 at 14:41
  • 1
    There's a good response for that here: http://stackoverflow.com/questions/4238204/is-it-possible-to-mix-template-derived-c-classes-with-qts-q-object – Tomaz Canabrava Apr 12 '17 at 14:55