Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QListView, headerdata and data never called



  • Hi everyone,

    I just want to create a model that contains two custom datas (two QString) and display it in a QListView.
    I have some issue: nothing is shown when I insert a new row and a new data inside it.

    I join you my model. m_items is a QList of ImageSegmentationItem (a class with two QString).

    When I debug my code, I never go inside the headerData method neither data method.
    I don't understand what I did wrong.

    Thank you

    ImageSegmentationModel::ImageSegmentationModel(QObject *parent)
    	: QAbstractListModel(parent)
    {
    }
    
    QVariant ImageSegmentationModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
    	if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    	{
    		if (section == 0)
    		{
    			return tr("Image Path");
    		}
    		else if (section == 1)
    		{
    			return tr("Segmentation Path");
    		}
    	}
    	return QVariant();
    }
    
    int ImageSegmentationModel::rowCount(const QModelIndex &parent) const
    {
    	return m_items.size();
    }
    
    int ImageSegmentationModel::columnCount(const QModelIndex &parent) const
    {
    	return 2;
    }
    
    QVariant ImageSegmentationModel::data(const QModelIndex &index, int role) const
    {
    	if (!index.isValid())
    		return QVariant();
    
    	if (role == Qt::DisplayRole)
    	{
    		if (index.column() == 0)
    		{
    			return m_items.at(index.row()).imagePath();
    		}
    		else if (index.column() == 1)
    		{
    			return m_items.at(index.row()).segmentationPath();
    		}
    	}
    
    	return QVariant();
    }
    
    bool ImageSegmentationModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
    	bool res = false;
    	if (index.isValid() && role == Qt::EditRole)
    	{
    		if (m_items.size() > index.row())
    		{
    			if (value.canConvert<QString>())
    			{
    				QString valStr = value.toString();
    				if (index.column() == 0)
    				{
    					m_items[index.row()].setImagePath(valStr);
    					res = true;
    				}
    				else if (index.column() == 1)
    				{
    					m_items[index.row()].setSegmentationPath(valStr);
    					res = true;
    				}
    			}
    			if (res)
    			{
    				emit dataChanged(index, index);
    			}
    		}
    	}
    	return res;
    }
    

    Edit: I remove the test on the parent in the rowCount method and now, the line are show but only the first column (still without the header)


  • Qt Champions 2019

    @Athius said in QListView, headerdata and data never called:

    but only the first column

    https://doc.qt.io/qt-5/qabstractlistmodel.html#details :
    "The QAbstractListModel class provides an abstract model that can be subclassed to create one-dimensional list models."

    So why should it be called for the second column? Looks like you want QAbstractTableModel instead.



  • @Christian-Ehrlicher said in QListView, headerdata and data never called:

    So why should it be called for the second column? Looks like you want QAbstractTableModel instead.

    Thank you.

    Because I thought that by overloading the columnCount method and always returning 2, the problem will fix but no.
    I change by a QAbstractTableModel and also by QAbstractItemModel before I understand that the problem was coming from the view: I change the QListView by a QTableView and it's all working now (I keep the model as described before).


  • Qt Champions 2019

    @Athius said in QListView, headerdata and data never called:

    Because I thought that by overloading the columnCount method and always returning 2

    A QAbstractListModel is made for 1 column, you misuse the desired usecase. This can lead to unexpected things. If you want a table, use a table and not a chair.


Log in to reply