3

I'm trying to use the same model to display pieces of information on 2 different kind of view.

I need to show information about 150 objects that have a description and can be either on or off.

One of the view is a summary of the on/off states of my objects in a table (15 by 10) of icons.

The other view is a list of 150 rows that display the state of the objects and their descriptions.

I tried to subclass a QAbstractTableModel and return a different rowCount and columnCount value depending of the view used and it works (my 150 objects are all shown in the table and in the list) but it remove the clear separation between model and view given that I need to specifically tell the model which view is using it and it doesn't work as expected when I try to link the 2 selection models of the views together because QModelIndex changes when the row and columns counts change.

Any idea of what could be a better approach to my problem or a way to solve the selection issue?

EDIT due to @ramtheconqueror response:

The response from ramtheconqueror led me to the right direction but surprisingly I discovered that the ProxyModel takes the overriden columnCount and rowCount function into account for the widget size calculation but do not actually use them for the widget indexes.

I mean that regarding my example above, the ListView using the new ProxyModel was a widget with enough space for 150 rows but was only showing the first 10 (rowCount in the source model).

Therefore, I did it the other way around and used a QAbstractListModel as the main model an set the QTableView to use the Proxy model but again the table was correctly a 15 by 10 widget but with content only on the first column.
I had to change the return value of ColumnCount to 15 on my QAbstractListModel subclass to get the correct result (even if it's really a list and therefore only contains one column).

Am I doing something wrong? I just don't understand why it behaves like that...

RAM
  • 2,257
  • 2
  • 19
  • 41
  • 2
    I would implement 2 models that share the same raw data pool or one proxy model that depends on another model (not QAbstractProxyModel) to accomplish your task. – OnWhenReady Feb 05 '16 at 14:47

1 Answers1

2

As you already have QAbstractTableModel, create a proxy model for the list view. Simple implementation would be like

TableModel* tableModel = new TableModel();
.....
tableView->setModel(tableModel);

class ListProxyModel : public QSortFilterProxyModel
{
   Q_OBJECT

   public:
   virtual int columnCount(const QModelIndex& idx) const { return 1; }

   virtual QVariant data(const QModelIndex& idx, int role) const {
      ... get the actual model index 
      ... ask the tableModel for the actual data
      ... construct the data (string / int / bool etc) 
      return the data;
   }
}

QListView listView = new QListView();
ListProxyModel* listModel = new ListProxyModel();
listModel->setModel(tableModel);
listView->setModel(listModel);
ramtheconqueror
  • 1,907
  • 1
  • 22
  • 35
  • 2
    You may use `QIdentityProxyModel` instead of `QSortFilterProxyModel` for such cases, because you don't need any filtering or sorting. – Dmitry Sazonov Feb 05 '16 at 15:20
  • "that would work as well" Or, rather, that's what you should have done in the first place. It's not about what works, it's about writing code that clearly conveys its purpose *to the human reader*. Just because the machine can run it doesn't make it proper. Remember: code is for humans first, machines second. – Kuba hasn't forgotten Monica Feb 05 '16 at 18:50
  • As I put in the edit, I still don't clearly understand why I need to set, in the ListModel, a number of column equal to the number of column in the tableView but anyway this answer helped me a lot so I mark it as accepted. Thanks for your help and advice. – Bertrand Thelen Feb 09 '16 at 13:36