PDA

View Full Version : Validating multiple discontinuous ranges



Nivek
19th August 2010, 17:27
I have a large amount of generated QLineEdits that I want to put numerical range validation on. QIntValidator provides this for a single range, but I want to make it possible to validate on an arbitrary number of discontinuous ranges as read from an XML file. For example, I may want the lineEdit to be able to take integers in the range of (0-50), (100-200) and (1000-1400), but not the ranges in between those.

I had the idea of reimplementing QIntValidator to contain a list of QIntValidators for each range I want to add to it, but looking at the documentation further I don't think that will work very well.

I guess the other option would be parsing the xml myself and constructing regular expressions at run time for use in QRegExpValidator, but that seems excessive in terms of both time and effort and performance for the payoff.

This would be simple if Qt allowed multiple validators to be put on one object, but if you set a more than one validator the second one replaces the first one.

Thanks in advance for any ideas.

tbscope
19th August 2010, 17:52
Why not create your own validator?

Nivek
19th August 2010, 18:03
Why not create your own validator?

Well, a good way of doing that is essentially what I'm asking about. How would I go about doing that? Could I make a validator that keeps its own list of one validator for each separate range?

tbscope
19th August 2010, 19:04
This is a five second example. The logic is all wrong, that's up to you to fix :-)
But this is the idea:

header file


#ifndef QRANGEVALIDATOR_H
#define QRANGEVALIDATOR_H

#include <QValidator>

#include <QList>
#include <QString>

struct Range
{
int low;
int high;
};

class QRangeValidator : public QValidator
{
Q_OBJECT
public:
explicit QRangeValidator(QObject *parent = 0);

void addRange(int low, int high);

QValidator::State validate(QString &input, int &pos) const;

signals:

public slots:

private:
QList<Range *> m_ranges;

};

#endif // QRANGEVALIDATOR_H


cpp file


#include "qrangevalidator.h"

QRangeValidator::QRangeValidator(QObject *parent) :
QValidator(parent)
{
}

void QRangeValidator::addRange(int low, int high)
{
Range *newRange = new Range;
newRange->low = low;
newRange->high = high;

m_ranges.append(newRange);
}

QValidator::State QRangeValidator::validate(QString &input, int &pos) const
{
int value = input.toInt();
bool inRanges = false;

foreach(Range *r, m_ranges) {
if ( (value >= r->low) && (value <= r->high) ) {
inRanges = true;
break;
}
}

if (!inRanges)
return QValidator::Acceptable;
else
return QValidator::Invalid;
}



Simple usage example:


#include "widget.h"
#include "ui_widget.h"

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

m_validator = new QRangeValidator;

m_validator->addRange(10, 20);
m_validator->addRange(30, 40);

connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(checkRange()));
}

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

void Widget::checkRange()
{
int pos = 0;
QString txt = ui->lineEdit->text();

if (m_validator->validate(txt, pos))
ui->lineEdit->setText("Invalid number");
else
ui->lineEdit->setText("Yes, correct");

}

Nivek
19th August 2010, 20:26
Thanks tbscope, I'll try that out!