PDA

View Full Version : QPlainTextEdit and input filtering



paul.schwann
12th October 2009, 08:23
Hi there,

I want to make a QPlainTextEdit component restricting the input to only the characters '0' and '1'. Besides that, all the "control keys" for cut/copy/paste, tab for focus change etc. shall still work. So far, I haven't been successful and thus, asking for your help.

My expectation was, that QPlainTextEdit has one method where all the text going inside is handled. As far as I can tell, that is not the case.

Here is what I have done so far:

----
Idea #1: Use some signal/slot to intercept text which shall not go inside the edit. The obvious is the textChanged() signal but this is called if the text is already placed in the editor (too late).
Is there a signal which is called before the text is placed in the edit?

-----
Idea #2: Install event filter and discard all input except '0' and '1'

MyQPlainTextEdit edit;
..
MyQPlainTextEdit::MyQPlainTextEdit(QWidget *parent) : QPlainTextEdit(parent) {
...
installEventFilter(this);
}

bool MyQPlainTextEdit::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);

if ((keyEvent->text() != "") && (keyEvent->text() != "0") && (keyEvent->text() != "1")) {
return true;
}
}

// standard event processing
return QObject::eventFilter(obj, event);
}


The problem is that I cannot reliable distinguish between actual characters shown in the widget and keystrokes potentially doing some control things. For example: I can enter a '0' or '1' (shows up in the text) or I can enter a Ctrl-'0' or Ctrl-'1' (works also with AltGr and so on).
I feel that intercepting plain key event is a bit too low level for my purpose...
---

Idea #3
Using a custom QTextCursor and overriding insertText(). As it turns out, these methods are only called if I insert text into the editor programmatically. User input is not seen by these functions.

-----

What am I doing wrong? What do you suggest? Thanks for your help and any hits you can give me!

Regards,
Paul

wysota
12th October 2009, 10:06
Intercept key press event and discard all input besides "0" and "1" if and only if there are no keyboard modifiers active (or if just Shift modifier is active).

paul.schwann
12th October 2009, 10:27
Hi wysota!

Thanks for your reply. Unfortunately, I am unable to turn your suggestion into working code. I tried:



bool MyQPlaintTextEditor::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);

if ((keyEvent->modifiers() == 0) && (keyEvent->text() != "0") && (keyEvent->text() != "1")) {
return true;
}
}

// standard event processing
return QObject::eventFilter(obj, event);
}


I still can e.g. press AltGr-0 and get a "}" -> AltGr doesn't seem to be catched by modifiers(). Besides that, the code above doesn't allow me to navigate with cursor keys or use backspace. Do I really have to check all those keycodes and let them though? This seems odd to me. But as I said already: I think that playing with the key codes it too low level for my purpose...

Any other ideas? Thanks a lot!

Regards,
Paul

wysota
12th October 2009, 10:38
I still can e.g. press AltGr-0 and get a "}" -> AltGr doesn't seem to be catched by modifiers()
It should be.


Do I really have to check all those keycodes and let them though? This seems odd to me.
What would not seem odd to you?

I think that playing with the key codes it too low level for my purpose...
What is the purpose? What if I paste some text which is not composed from 0 and 1? Is it valid or not? If not, then you have to check the contents of the text edit each time it changes using the QTextDocument::contentsChange() signal and simply correct the changes you don't want. Note that you may wreck undo/redo with this though.

squidge
12th October 2009, 10:38
I don't like using eventFilter unless I can help it. I prefer to subclass the widget and override QPlainTextEdit::keyPressEvent, and then use QApplication::keyboardModifiers to detect which control keys are pressed.

paul.schwann
12th October 2009, 12:03
It should be.


What would not seem odd to you?

What is the purpose? What if I paste some text which is not composed from 0 and 1? Is it valid or not? If not, then you have to check the contents of the text edit each time it changes using the QTextDocument::contentsChange() signal and simply correct the changes you don't want. Note that you may wreck undo/redo with this though.
Hi Wysota,

I am a bit lost here...

It seems odd to me that I have to fiddle with tons of conditions although all I want is to avoid some text appear in the editor field. Why do I have to take care about all the control keys (which I don't even know)?

Regarding the copy/paste problem: I expect to be able to hook into the copy/paste functions of the QPlainTextEdit and either filter all non-0/1 characters out of the text being pasted or at least reject the pase action if other than 0/1 is in the text.

Let me ask another question: What function is called (and thus, I can override) if the QPlainTextEdit is supposed to insert/append additional text (or set new text)? Is there a single function responsible for this?
This function might also be part of the QTextDocument instead of the QPlainTextEdit.
-- I wasn't able to locate such a function (it may exist or not).

Thanks & Regards,
Paul