Reputation: 125
I have a QTableView which has some QString based items in its model. I implemented setData in my table model, so editing is working (I can change the data in the cell, setData is called to update the model, and the table is properly updated).
Currently setData is only called when the user is done with editing, e.g. after they hit Enter or click out of the text entry box to finalize the text entry. I want to update other other parts of the table while the user is typing/editing into the text edit control instead of after they're done and the edited contents are finalized.
A simple example of what I want to have is for the next table cell to display a count of how many characters have been entered into the cell being edited, but to do this as the user is typing/editing the cell contents, not just after the edit is finalized and setData is called.
Any pointers to what I should be looking for? Thanks!
Upvotes: 1
Views: 3253
Reputation: 29886
You can subclass QStyledItemDelegate
and commit the data whenever something changes, and then set that delegate for the view with QAbstractItemView::setItemDelegate
.
class MyDelegate : public QStyledItemDelegate {
QSignalMapper *mapper;
public:
MyDelegate(QObject*parent = 0)
: QStyledItemDelegate(parent)
, mapper(new QSignalMapper(this))
{
connect(mapper, SIGNAL(mapped(QWidget*)), SIGNAL(commitData(QWidget*)));
}
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option,
const QModelIndex & index ) const
{
QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
if(qobject_cast<QLineEdit*>(editor)) {
connect(editor, SIGNAL(textChanged(QString)), mapper, SLOT(map()));
mapper->setMapping(editor, editor);
}
return editor;
}
};
Upvotes: 2
Reputation: 496
The answer offered by @alexisdm did not work for me when I needed a persistent
editor enabled by QAbstractTableModel::setPersistentEditor(QModelIndex())
.
The following solves this problem:
class Delegate : public QStyledItemDelegate
{
Q_OBJECT
public:
// ... omitted for brevity
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override
{
auto *editor = static_cast<QLineEdit*>(
QStyledItemDelegate::createEditor(parent, option, index));
if (editor) {
connect(editor,
&QLineEdit::textChanged,
[=] (const QString &)
{
const_cast<Delegate*>(this)->commitData(editor);
});
}
return editor;
}
// ... omitted for brevity
};
We simply cast the constness from this
and make it commit data for the editor.
Note that in the lambda we capture the editor
variable by value [=]
because otherwise, capturing with reference would make the value of editor
undefined when the function runs out of scope.
Upvotes: 1