I recently made a sample to become (more) familiar with QStyledItemDelegate concerning inline editing of cells:
In this sample, I did the update of underlying data model overloading QStyledItemDelegate::setModelData().
After having read this question, I just tested what happens if input is finished (or strictly speaking: aborted) by ESC. This is what I observed:
The underlying data is kept unchanged.
Digging deeper (i.e. setting a break-point into my overloaded setModelData()), I observed setModelData() is even not called in this case.
May be, the OPs issue can be solved easily by a little re-design of his delegate.
Finally, my derived class (declaration) I used to achieve a "full-featured" delegate to edit table cells inline:
class ValueNameDelegate: public QStyledItemDelegate {
// methods:
public:
/// @name Construction & Destruction
//@{
/// constructor.
ValueNameDelegate();
/// destructor.
virtual ~ValueNameDelegate() = default;
// disabled:
ValueNameDelegate(const ValueNameDelegate&) = delete;
ValueNameDelegate& operator=(const ValueNameDelegate&) = delete;
//@}
protected:
/// @name Overloaded Event Handlers
//@{
// inserts editor in table (by setParent(pQParent)) and
// returns the editor widget to edit cell.
virtual QWidget* createEditor(
QWidget *pQParent, const QStyleOptionViewItem &qOption,
const QModelIndex &qMIndex) const override;
// removes editor from table (by setParent(nullptr)).
virtual void destroyEditor(
QWidget *pQEditor, const QModelIndex &qMIndex) const override;
// reads data from table model and updates editor.
virtual void setEditorData(
QWidget *pQEditor, const QModelIndex &qMIndex) const override;
// reads data from editor and updates table model.
virtual void setModelData(
QWidget *pQEditor, QAbstractItemModel *pQModel,
const QModelIndex &qMIndex) const override;
//@}
};
Note:
In my case, there is only one editor widget created before-hand. It is re-used for every cell editing (instead of creating for each edit a new one).
This is a little bit different from the Qt Spin Box Delegate Example but works as expected.
I cannot imagine how this shouldn't make any difference concerning the OPs problem.
According to feed-back, OP wants to handle the focus-lose event like abort of input. This is in opposition how this is handled by default in QLineEdit.
So, my solution is to provide an overloaded version of QLineEdit. Instead of changing the behavior of QLineEdit, it simply tracks in a member bool _confirmed whether Enter was pressed. The most tricky part was to identify another suitable event or signal to reset the member. Finally, I decided that focusOutEvent() is just called at the right time and hence suitable for this task.
testQLineEdit-Finished.cc:
#include <QtWidgets>
class LineEdit: public QLineEdit {
private:
// flag: true ... last finished editing was confirmed
bool _confirmed;
public:
// Construction & Destruction
explicit LineEdit(
const QString &contents = QString(), QWidget *pQParent = nullptr):
QLineEdit(contents, pQParent),
_confirmed(false)
{
QObject::connect(this, &QLineEdit::returnPressed,
[this](){ onSigReturnPressed(); });
}
LineEdit(QWidget *pQParent): LineEdit(QString(), pQParent) { }
virtual ~LineEdit() = default;
LineEdit(const LineEdit&) = delete;
LineEdit& operator=(const LineEdit&) = delete;
public:
// returns whether last finished editing was confirmed.
bool isConfirmed() { return _confirmed; }
protected:
virtual void focusOutEvent(QFocusEvent *pQEvent) override
{
_confirmed = false;
QLineEdit::focusOutEvent(pQEvent);
}
private:
void onSigReturnPressed() { _confirmed = true; }
};
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup GUI
LineEdit qEdit(QString::fromUtf8("Hello World"));
qEdit.show();
// install signal handlers
QObject::connect(&qEdit, &LineEdit::editingFinished,
[&]() {
qDebug() << "Edit confirmed:" << qEdit.isConfirmed();
});
// runtime loop
return app.exec();
}

The output of Edit confirmed: true was achieved by pressing Enter, the false lines by clicking around.
This is done rather simple and might be done more sophisticated. However, it shows the principle achieved with a rather low number of code lines.