QIntValidator gotcha

Programmers are not to be measured by their ingenuity and their logic but by the completeness of their case analysis.

—Alan J. Perlis, “Epigrams on Programming”

The problem I’m going to present is actually dirt-simple, and its causes are even described in the official docs. Yet the Google itself couldn’t find the solution when I needed it, so let’s help the tech giant out by blogging about it.

A few days ago I was working on a seemingly simple task: given a description of an integer type (e.g. signed 32-bit, unsigned 64-bit), ensure that a QLineEdit will only accept numbers that fit into that type. Luckily, Qt already has some input-checking facilities, letting us attach a so-called validator to an input field. Furthermore, there’s a standard QIntValidator that determines if an integer is in the given range—just what I needed!

I tested it with unsigned 8-bit first, and everything went well. But then I tried signed type and immediately discovered that I can input “128” even though the upper bound is 127. But why? Maybe QIntValidator’s range is actually a half-open interval? Nope, it’s a closed one all right. Have I made an error calculating the bounds? A few qDebug()s confirmed I didn’t, and hard-coding the upper limit didn’t change a thing either. What the hell?

Going through the customary ritual of losing faith first in myself, then in my compiler, and finally in my machine, I printed out the result the validator returns to QLineEdit. Sure enough, it was Acceptable for -128, and Intermediate for 128. Because, y’know, “128” is just “-128” without a minus; the validator deems it okay for the user to input their numbers in whichever order they please.

So if you’ve come here from Google, don’t worry: QIntValidator’s lower bound is inclusive; and QIntValidator’s upper bound is inclusive, too. You just have a range that’s “sloped” towards the negative numbers, and thus your validator seemingly accepts values bigger than it should. Connect to QLineEdit::​textEdited(const QString&) and change input’s border color to red or something if the result is not Acceptable, and you’ll be fine.

Drop me a line! (wonder where’s the comments form?)