QTableView: edit cell after validation failure
-
I'm trying to implement a custom validator for a
QTableView:customdelegateoperators.h
#ifndef CUSTOMDELEGATEOPERATORS_H #define CUSTOMDELEGATEOPERATORS_H #include <QStyledItemDelegate> #include "modeloperators.h" class CustomDelegateOperators : public QStyledItemDelegate { Q_OBJECT public: CustomDelegateOperators(QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setModel(ModelOperators *model) { _model = model; } private: ModelOperators *_model; signals: void validationFailed(QModelIndex index) const; }; #endif // CUSTOMDELEGATEOPERATORS_Hcustomdelegateoperators.cpp
#include "customdelegateoperators.h" #include <QRegExpValidator> #include <QLineEdit> CustomDelegateOperators::CustomDelegateOperators(QObject *parent) : QStyledItemDelegate(parent) { } QWidget *CustomDelegateOperators::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex & index ) const { switch (index.column()) { case MODEL_OPERATORS_COL_NAME: { QLineEdit *editor = new QLineEdit(parent); QRegExp rx("^(?!\\s*$).+"); return editor; } case MODEL_OPERATORS_COL_SIGNATURE: { QLineEdit *editor = new QLineEdit(parent); return editor; } default: return QStyledItemDelegate::createEditor(parent, option, index); break; } return nullptr; } void CustomDelegateOperators::setEditorData(QWidget *editor, const QModelIndex &index) const { switch (index.column()) { case MODEL_OPERATORS_COL_NAME: case MODEL_OPERATORS_COL_SIGNATURE: { QString value = index.model()->data(index, Qt::EditRole).toString(); QLineEdit *item = qobject_cast<QLineEdit *>(editor); item->setText(value); break; } default: QStyledItemDelegate::setEditorData(editor, index); break; } } void CustomDelegateOperators::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { switch (index.column()) { case MODEL_OPERATORS_COL_NAME: { QLineEdit *item = qobject_cast<QLineEdit *>(editor); QRegExp rx("^(?!\\s*$).+"); QRegExpValidator *validator = new QRegExpValidator(rx); QString value = item->text(); int pos = 0; if (validator->validate(value, pos) == QValidator::Acceptable) model->setData(index, value, Qt::EditRole); else emit validationFailed(index); break; } default: QStyledItemDelegate::setModelData(editor, model, index); break; } } void CustomDelegateOperators::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { editor->setGeometry(option.rect); }Usage:
ui->tableOperators->setModel(&_modelOperators); ui->tableOperators->sortByColumn(MODEL_OPERATORS_COL_NAME); ui->tableOperators->setItemDelegate(&_delegateOperators); connect(&_delegateOperators, &CustomDelegateOperators::validationFailed, this, &DialogSettings::tableOperators_validationFailed); // ... void DialogSettings::tableOperators_validationFailed(QModelIndex index) { QMessageBox::warning(this, tr("Operators"), tr("Insert a valid value")); ui->tableOperators->setCurrentIndex(index); ui->tableOperators->edit(index); }The goal is to avoid the user to enter a null value in the first column (
MODEL_OPERATORS_COL_NAME). If it happens a message box should appear and then the related cell should be edited gain, until the user enters a valid data.It works, but after closing the message box the current index is not set on the desired cell and no edit is activated ("edit: editing failed" appears in the application output window).
What's wrong here?
-
Hi,
Are you aware that you don't set any validator on your line edit in
createEditor?On a side note, you should fix your thread title. An email address doesn't make much sense.
-
Hi,
Are you aware that you don't set any validator on your line edit in
createEditor?On a side note, you should fix your thread title. An email address doesn't make much sense.
@SGaist said
Are you aware that you don't set any validator on your line edit in
createEditor?Yes I know. I use the validator in
setModelData()to decide whether update the model or emit a signal.
Here an example of this approach: https://stackoverflow.com/a/26614960 (second solution in the accepted answer).On a side note, you should fix your thread title. An email address doesn't make much sense.
Oh dear, I don't know how that happened. I wrote a real title, I'm sure.
-
@Mark81 said in QTableView: edit cell after validation failure:
setCurrentIndex
Looks like you are trying to fix that in this thread, correct ?
-
@Mark81 said in QTableView: edit cell after validation failure:
setCurrentIndex
Looks like you are trying to fix that in this thread, correct ?
@SGaist said in QTableView: edit cell after validation failure:
Looks like you are trying to fix that in this thread, correct ?
Well, actually these are two separated questions.
I'm afraid this code (in this question) doesn't work because when the signal is catch the execution is still inside the delegate function. So the index are overwritten when the code exits from the delegate.Here I'm asking how to correctly handle such a validation.
In the other thread I'm learning how to pass parameters to a singleshot call. As side effect it might be a workaround to fix this (but I don't think its THE solution).