I have a Qt widget which should only accept a hex string as input. It is very simple to restrict the input characters to [0-9A-Fa-f]
, but I would like to have it display with a delimiter between "bytes" so for example if the delimiter is a space, and the user types 0011223344
I would like the line edit to display 00 11 22 33 44
Now if the user presses the backspace key 3 times, then I want it to display 00 11 22 3
.
I almost have what i want, so far there is only one subtle bug involving using the delete key to remove a delimiter. Does anyone have a better way to implement this validator? Here's my code so far:
class HexStringValidator : public QValidator {
public:
HexStringValidator(QObject * parent) : QValidator(parent) {}
public:
virtual void fixup(QString &input) const {
QString temp;
int index = 0;
// every 2 digits insert a space if they didn't explicitly type one
Q_FOREACH(QChar ch, input) {
if(std::isxdigit(ch.toAscii())) {
if(index != 0 && (index & 1) == 0) {
temp += ' ';
}
temp += ch.toUpper();
++index;
}
}
input = temp;
}
virtual State validate(QString &input, int &pos) const {
if(!input.isEmpty()) {
// TODO: can we detect if the char which was JUST deleted
// (if any was deleted) was a space? and special case this?
// as to not have the bug in this case?
const int char_pos = pos - input.left(pos).count(' ');
int chars = 0;
fixup(input);
pos = 0;
while(chars != char_pos) {
if(input[pos] != ' ') {
++chars;
}
++pos;
}
// favor the right side of a space
if(input[pos] == ' ') {
++pos;
}
}
return QValidator::Acceptable;
}
};
For now this code is functional enough, but I'd love to have it work 100% as expected. Obviously the ideal would be the just separate the display of the hex string from the actual characters stored in the QLineEdit
's internal buffer but I have no idea where to start with that and I imagine is a non-trivial undertaking.
In essence, I would like to have a Validator which conforms to this regex: "[0-9A-Fa-f]( [0-9A-Fa-f])*"
but I don't want the user to ever have to type a space as delimiter. Likewise, when editing what they types, the spaces should be managed implicitly.
Evan, try this:
QLineEdit * edt = new QLineEdit( this );
edt->setInputMask( "Hh hh hh hh" );
The inputMask takes care of the spacing, and the "h" stands for a optional hex character (the "H" for a non-optional). Only drawback: You have to know the maximum input length in advance. My example above allows only for four bytes.
Best regards, Robin
I will propose three approaches :
You can reimplement the QLineEdit::keyPressEvent()
to handle backslash differently when the character just left to the QLineEdit
's cursor is a space. Using this approach, you can also automatically add spaces when a new character is typed.
Another approach is to create a new slot, connected to the QLineEdit::textChanged()
signal. This signal is emitted when the text is changed. In this slot, you can handle the creation and deletion of spaces accordingly to your needs.
Finally, you can create a new class, derived from QLineEdit
that reimplements the QLineEdit::paintEvent()
method. With this approach, you can display space between your hex words that are not stored in the QLineEdit
buffer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With