Working with a QTableView
and QAbstractTableModel
- when the model emits a dataChanged
event for the cell being edited, the string the user has typed in the cell (but not pressed enter to 'commit' the edit) is erased.
Example: Click a cell, type '123', cell is still in edit mode waiting for more text, dataChanged
is emitted and the '123' is erased, leaving an empty cell in edit mode.
Does anyone know how to stop this behaviour, or how the model can detect when the cell is being edited to prevent dataChanged
events being raised for that cell?
I had the same problem. The thing is, that data()
function is called with different role
parameter. For displaying role==Qt::DisplayRole
and while editing it is called with role==Qt::EditRole
. For example try changing
QVariant MyModel::data(const QModelIndex & index, int role) const
{
if (role == Qt::DisplayRole)
return QString("Text to Edit");
}
to
QVariant MyModel::data(const QModelIndex & index, int role) const
{
if (role == Qt::DisplayRole || role == Qt::EditRole)
return QString("Text to Edit");
}
that should do the trick
I had the same problem and found an approach without writing my own Delegate:
The problem is exactly how you described it: The data gets updated in the Background and everything you Edit gets cleared out because the dataChanged Event updates all values thus calling the data function, which returns an empty QVariant() Object if nothing is specified for the Qt::EditRole. Even Leonid's answer would always overwrite your edits with the same QString("Text to Edit").
So what I did was this:
Introduce a member variable and dafine it mutable so it can be changed by the const data function:
mutable bool m_updateData = true;
In your background data updating function, check for m_update date before emmitting the dataChanged Signal:
if (m_updateData)
emit(dataChanged(index, index));
In your data function, check for the edit role and set m_updateData to false:
if (role == Qt::EditRole)
{
m_updateData = false;
}
After the Edit is finished, the setData function is called, where you update the data in your model. Reset m_updateDate to true after you have done that.
This works perfectly for me :)
Check your model class, you should override the setData method in your model. If every thing is correct it will update model after editing data... please let me know if you have another implementation
bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
int row = index.row();
int col = index.column();
//// change data
emit(dataChanged(index, index));
return true;
}
return false;
}
I think that you should use dataChanged
event only for indexes that are not being edited or only for Qt::ItemDataRole::DisplayRole
.
E.g. to update only second column for every row use:
emit dataChanged(index(0, 1),
index(rowCount() - 1, 1),
QVector<int>{ Qt::ItemDataRole::DisplayRole });