开发者

QValidator for hex input

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开发者_如何学Go-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.


Robin's solution is good and works. But I think you can do best!
Use this for input mask:

ui->lineEdit->setInputMask("HH-HH-HH-HH");

and in the ui, R-click on lineEdit -> Go to Slots... -> textChanged. In the slot function write this code:

int c = ui->lineEdit->cursorPosition();
ui->lineEdit->setText(arg1.toUpper());
ui->lineEdit->setCursorPosition(c); // to not jump cursor's position

Now you have a lineEdit with Hex input, in uppercase, with dash-separators.

have a good code time :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜