Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTableView: edit cell after validation failure
Forum Updated to NodeBB v4.3 + New Features

QTableView: edit cell after validation failure

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 2 Posters 924 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mark81
    wrote on last edited by Mark81
    #1

    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_H
    

    customdelegateoperators.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?

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      M 1 Reply Last reply
      0
      • SGaistS SGaist

        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.

        M Offline
        M Offline
        Mark81
        wrote on last edited by Mark81
        #3

        @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.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @Mark81 said in QTableView: edit cell after validation failure:

          setCurrentIndex

          Looks like you are trying to fix that in this thread, correct ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          M 1 Reply Last reply
          0
          • SGaistS SGaist

            @Mark81 said in QTableView: edit cell after validation failure:

            setCurrentIndex

            Looks like you are trying to fix that in this thread, correct ?

            M Offline
            M Offline
            Mark81
            wrote on last edited by
            #5

            @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).

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved