I realize this wins me necro-poster of the year, but I felt that this information would be beneficial to a lot of people.
The IP Address Validation (by Regex) and Mask issue was a tough cookie to crack. Setting one without the other usually worked but was flawed. I'd either not get the visual effect of having dots in the box or the user could enter invalid addresses (octets with values >255). Setting them together made it impossible to enter any value.
I found that the Class provided by Wysota solved the problem, but there was another limitation: it required you to use blanks as 0's, when I would prefer to use spaces.
Side-Note: I know a lot of people are looking for a good IP Address RegEx and here's the best one I've found so far:
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
To copy to clipboard, switch view to plain text mode
What I ended up doing was expanding the code that Wysota provided to allow for spaces. Here is the excerpt:
if (slist[i].isEmpty() || slist[i] == " ") {
emptyGroup = true;
continue;
}
if (slist[i].isEmpty() || slist[i] == " ") {
emptyGroup = true;
continue;
}
To copy to clipboard, switch view to plain text mode
Now that fully works with a Mask of "000.000.000.000; " and your users cannot physically enter an invalid address.
Yay! That is settled. Now for my next problem. My specific programming needs also include being able to enter in a CIDR, which has a Mask of "009.009.009.009\/09". The first part of that works just like IP Addresses and the last part is limited to integers of 0-32.
To accomplish this, I duplicated Wysota's IP Address class to CIDRValidator. Here is the full code (tested and works):
public:
void fixup
(QString &/*input*/) const { } State validate
(QString &input,
int &/*pos*/) const { if(input.isEmpty()) { return Acceptable; }
int s = slist.size();
if (s > 4) { return Invalid; }
bool emptyGroup = false;
for (int i=0; i<s; i++) {
bool ok, ok2 = true;
if (slist[i].isEmpty()
|| slist[i] == " "
|| ssplit.count() > 1 && (ssplit[0] == " " || ssplit[1] == " "))
{
emptyGroup = true;
continue;
}
int val = (ssplit.count() > 1 ? ssplit[0].toInt(&ok) : slist[i].toInt(&ok));
int cidval = (ssplit.count() > 1 ? ssplit[1].toInt(&ok2) : -1);
if((!ok || val<0 || val>255) || (ssplit.count() > 1 && (!ok2 || cidval<0 || cidval>32))) { return Invalid; }
}
if(s<4 || emptyGroup) return Intermediate;
return Acceptable;
}
};
class CIDRValidator : public QValidator {
public:
CIDRValidator(QObject *parent=0) : QValidator(parent) { }
void fixup(QString &/*input*/) const { }
State validate(QString &input, int &/*pos*/) const {
if(input.isEmpty()) { return Acceptable; }
QStringList slist = input.split(".");
int s = slist.size();
if (s > 4) { return Invalid; }
bool emptyGroup = false;
for (int i=0; i<s; i++) {
bool ok, ok2 = true;
QStringList ssplit = slist[i].split('/');
if (slist[i].isEmpty()
|| slist[i] == " "
|| ssplit.count() > 1 && (ssplit[0] == " " || ssplit[1] == " "))
{
emptyGroup = true;
continue;
}
int val = (ssplit.count() > 1 ? ssplit[0].toInt(&ok) : slist[i].toInt(&ok));
int cidval = (ssplit.count() > 1 ? ssplit[1].toInt(&ok2) : -1);
if((!ok || val<0 || val>255) || (ssplit.count() > 1 && (!ok2 || cidval<0 || cidval>32))) { return Invalid; }
}
if(s<4 || emptyGroup) return Intermediate;
return Acceptable;
}
};
To copy to clipboard, switch view to plain text mode
I hope this information helps future searchers with setting up their own IP Address and CIDR Address boxes.
Bookmarks