validationqmltableviewsudoku

MessageDialog is not showing when I validate a condition in a qml TableView


I have a TableView that has a Sudoku grid in it. I wanted to validate it so that a number cannot be placed in the same row or column using a c++ functions. When the user enters an invalid number it the MessageDialog should appear but that not happens. What can be the problem? This is the DialogBox and:

MessageDialog {
        id: msgDial
        text: "Invalid number."
        informativeText: "Do you want to save your changes?"
        buttons: MessageDialog.Ok

        onAccepted: msgDial.close()
    }

This is the TableView that I want to validate:


            TableView {
                anchors.fill: parent
                clip: true

                model: SudokuGrid {
                    id: grid
                }

                delegate: Rectangle {
                    required property var model
                    implicitWidth: 50
                    implicitHeight: 50

                    TextField {
                        anchors.fill: parent
                        text: model.display !== undefined ? model.display.toString() : ""

                        readOnly: model.display !== undefined && model.display !== 0

                        horizontalAlignment: TextInput.AlignHCenter
                        verticalAlignment: TextInput.AlignVCenter

                        background: Rectangle {
                            color: model.row % 2 ? "lightpink" : "lightblue"
                            border {
                                width: 1
                                color: "white"
                            }

                        }

                        color: "black"

                        validator: IntValidator {
                            bottom: 1
                            top: 9
                        }

                        onEditingFinished: {
                            if (text !== "" && model.display === 0) {
                                var enteredNumber = parseInt(text);
                                if (validator.validate(text, 0).valid && model.isNumberValid(model.row, model.column, enteredNumber)) {
                                    model.display = text;
                                } else {
                                    msgDial.open();
                                }
                            }
                        }

                        TableView.onCommit: {
                            if (text !== "" && model.display === 0) {
                                var enteredNumber = parseInt(text);

                                if (validator.validate(text, 0).valid && model.isNumberValid(model.row, model.column, enteredNumber)) {
                                    model.display = text;
                                } else {
                                    msgDial.open();
                                }
                            }
                        }

                    }

and this is the setData c++ function:

bool Grid::isNumberValid(int row, int col, int number) const
{

    for (int j = 0; j < 9; j++) {
        if (j != col && gridData[row][j] == number) {
            return false;
        }
    }

    for (int i = 0; i < 9; i++) {
        if (i != row && gridData[i][col] == number) {
            return false;
        }
    }

    return true;
}
bool Grid::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role == Qt::EditRole) {
        if (!checkIndex(index))
            return false;

        int inputValue = value.toInt();

        if (inputValue < 1 || inputValue > 9)
            return false;

        if (isNumberValid(index.row(), index.column(), inputValue)) {
            gridData[index.row()][index.column()] = inputValue;
            emit dataChanged(index, index);
            return true;
        } else {
            qDebug() << "Invalid number in the same row or column!";
        }
    }

    return false;
}

Maybe the fact that I used the id instead of an object passed to qml with setContextProperty that creates the class of the sudoku grid can be the problem? I am new to qml and I don't know what can be the problem.


Solution

  • To use the validator you should not call the IntValidator's validate method, you should check the TextField's acceptableInput property. For example:

    TextField {
        id: textField
        validator: IntValidator { bottom: 1; top: 9 }
        background: Rectangle {
            color: textField.acceptableInput ? "green" : "red"
        }
    }
    

    As this property is continuously available during the editing, I see there is no need to wait for onAccepted/onEditingFinished. Because you have a validator, I doubt that onAccepted/onEditingFinished would be triggered since your validator would be guarding against invalid input.