Validating Inputs using Qt

Introduction:

Validating the inputs is real and challenging task for the software developer. Users is always seem to type in inputs the developer did not expect. It's not really their fault, the developer needs to validate the input or allow the user to give the input that what you expect.

Qt developers have a wide range of input validators to choose from. In this article I'll review the various input validators available, and show the ways to help our users using QCompleter.


Mask Based Validation:

The easiest way to validate input in a QLineEdit is to use a mask. A mask is a special string that tells the line edit what type of characters the user can type next. If a user types a character that is not in range, it is simply ignored by the line edit.

A mask has both normal characters and special character. Each special character represents a character group. For example, the following code creates a QLineEdit that takes a numeric value in the form: +91-99-99-123423 (like mobile numbers in India).

#include <QtGui/QtGui>

int main(argc, **argv)
{
    QApplication app(argc, argv);

    QLineEdit e;
    e.setInputMask("9999-999-9999-999");
    e.show();

    app.exec();
}

Using QValidator:

Qt has an abstract class named QValidator that establishes the interface for validating the data. Two of QValidator's concrete subclasses can be used for numeric range checking: QIntValidator and QDoubleValidator.

QValidator has a pure virtual method called validate() that returns the following enumerated values:

  • Invalid – Not satisfied the required conditions. 
  • Intermediate – Not satisfied the required conditions. However, further inputs may produce an acceptable result. 
  • Acceptable – Satisfies the required conditions.

Regular Expression:

Regular expressions are powerful tools for validating the input. Regular expressions are offered by many languages like C++0x, python, Perl, Java and etc,. Qt provides class called QRegExp, which implements most of the Perl-style extended regular expression.

The QRegExp class provides pattern matching using regular expressions. It fully supports Unicode. QRegExp will expect or built the pattern string to qualify the valid input from expressions, quantifiers, and assertions.

  • Expression: The expression is a simple character. It can also be a set of characters enclosed in square brackets. For Ex: [ABCD] or [A-D].

  • Quantifier: Specify the number of occurrences of an expression that may appear in the matching expression. For Ex: X{1,1} means match one and only one X. X{1,5} means match a sequence of X characters that contains at least one X but no more than five. The below characters are used as a quantifiers. 
    • +        1 or more occurrences.
    • ?         0 or 1 occurrences. 
    • *         0 or more occurrences. 
    • {i,j}    At least i but not more than j occurrences. 

  • Assertions: Specify the boundaries of a matching effort. The below characters are used as an Assertions. 
    • The caret (^), if it is the first character in the regex, indicates that the match starts at the beginning of the string. 
    • The dollar sign ($), when it is the last character in the regex, means that the effort to match must continue to the end of the string. 
    • In addition, there are word boundary (\b) or non-word boundary (\B) assertions that help to focus the attention of the regex. 

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QRegExpValidator>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    int m_BotI, m_TopI;
    double m_BotD, m_TopD;

    QRegExpValidator *m_pValid;

public slots:
   void installMask();
   void showResult();

   void computeResult();

   void installPattern();
   void showRegResult();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->txtMask, SIGNAL(returnPressed()), this, SLOT(installMask()));
    connect(ui->txtInput, SIGNAL(returnPressed()), this, SLOT(showResult()));

    connect(ui->txtMask, SIGNAL(textChanged(QString)), this, SLOT(installMask()));
    connect(ui->txtInput, SIGNAL(textChanged(QString)), this, SLOT(showResult()));

    m_BotI = 5;
    m_TopI = 9;
    m_BotD = 99.9;
    m_TopD = 149.9;

    QIntValidator* iValid(new QIntValidator(m_BotI, m_TopI, this));
    QDoubleValidator* dValid(new QDoubleValidator(m_BotD, m_TopD, 2, this));
    ui->txtWork->setValidator(iValid);
    ui->txtPay->setValidator(dValid);

    connect(ui->txtWork, SIGNAL(returnPressed()), this, SLOT(computeResult()));
    connect(ui->txtPay, SIGNAL(returnPressed()), this, SLOT(computeResult()));


    m_pValid = new QRegExpValidator(this);

    connect(ui->txtPattern, SIGNAL(returnPressed()), this, SLOT(installPattern()));
    connect(ui->txtRegInput, SIGNAL(returnPressed()), this, SLOT(showRegResult()));

    connect(ui->txtPattern, SIGNAL(textChanged(QString)), this, SLOT(installPattern()));
    connect(ui->txtRegInput, SIGNAL(textChanged(QString)), this, SLOT(showRegResult()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::installMask() {
   ui->txtInput->setInputMask(ui->txtMask->text());
}

void MainWindow::showResult() {
    QString str = ui->txtInput->text();
    ui->txtResult->setText(str);
}


void MainWindow::computeResult() {

    double d = ui->txtPay->text().toDouble();
    int i = ui->txtWork->text().toInt();
    double res = d * i;
    ui->txtTotal->setText(QString("%1").arg(res));
}

void MainWindow::installPattern() {
    QRegExp rx(ui->txtPattern->text());
    m_pValid->setRegExp(rx);
    ui->txtRegInput->setValidator(m_pValid);
}

void MainWindow::showRegResult() {

    QString str = ui->txtRegInput->text();
    ui->txtRegResult->setText(str);
}

Note: In Qt 5, the new QRegularExpression class provides a Perl compatible implementation of regular expressions and is recommended in place of QRegExp.

References: