Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

how to uppercase first letter of sentense in QTextEdit



  • i would try to write a notepad and i try automatically upper first letter in each sentence. Does anyone know how to do it?


  • Moderators

    There is no direct way of doing it at least, but you could override the keyPressEvent() for QTextEdit and if it is going to be a normal key then with the help of QTextBoundaryFinder you can automatically make it upper case by inserting the character directly instead of letting the base implementation handle it for you.



  • Thanks Andy
    I've tried to use keyPressEvent(), but it comsumed each letter i've typed. I don't have experience with QtextBoundaryFinder(), it's one of my first's apps. Could you explain how to implement your method?


  • Moderators

    @stan09

    #ifndef MYTEXTEDIT_H
    #define MYTEXTEDIT_H
    
    #include <QTextEdit>
    #include <QKeyEvent>
    
    class myTextEdit : public QTextEdit
    {
        Q_OBJECT
    public:
        explicit myTextEdit(QWidget *parent = nullptr) : QTextEdit (parent)
        {
            
        }
    
    protected:
        virtual void keyPressEvent(QKeyEvent *e)override
        {
            if(toPlainText() == QString()){
                if((e->modifiers() & Qt::ShiftModifier)  == 0){
                    e->setModifiers((e->modifiers() | Qt::ShiftModifier));
                    QKeyEvent *event = new QKeyEvent(e->type(),e->key(),e->modifiers(),e->text().toUpper(), e->isAutoRepeat(),e->count());
                    QTextEdit::keyPressEvent(event);
                }
            } else {
                QTextEdit::keyPressEvent(e);
            }
        }
    };
    
    #endif // MYTEXTEDIT_H
    


  • @J.Hilk
    Yes, it works, but only with first letter in whole document. How add condition to repeat it after each dot?
    Btw, how can i add this code to projekt with base class QMainWindow? I can run your code only in separate projekt.


  • Moderators

    @stan09

    How add condition to repeat it after each dot?

    QString plaintText = toPlainText();
    if(plaintText == QString() || plaintText.endsWith('.'){
    

    btw, calling each key stroke toPlainText() maybe costly and/or overkill, it's just the first thing that came to my mind. You should investigate if that can't be done better.

    Btw, how can i add this code to projekt with base class QMainWindow?

    by creating a new instance ? Or do you mean inside the QDesigner ?
    In later case take a look here:
    https://doc.qt.io/qt-5/designer-using-custom-widgets.html



  • At least works fine.
    @J.Hilk

    btw, calling each key stroke toPlainText() maybe costly and/or overkill, it's just the first thing that came to my mind. You should investigate if that can't be done better.

    How to call out funcion only after pressing a space?


  • Lifetime Qt Champion

    @stan09

    The proper way is to use QTextCursor to scan backwards from your actual position and see if you have a dot '.' followed by a space ' '.

    A hacky solution would be to remember the last two keys that were pressed in keyPressEvent. That would, however, not work correctly if you move the cursor while writing.

    Regards



  • @stan09

    Yes, it works, but only with first letter in whole document. How add condition to repeat it after each dot?

    That's where you have to save state somehow to look at what has gone before. You have to figure the logic for what you want to achieve.

    Given that you're doing it via key press events. I wouldn't do @aha_1980's (self-acknowledged) hacky "just remember last two keys", you'll want to take account of things like if the user hits Backspace I would have thought at minimum, it just gets complicated.

    His using QTextCursor to look at what's in the line would be one way of getting the state you need.

    I will just say: you could do it all via textChanged slot & setText when needed (which won't be often, once per sentence), instead of the key press route. It will cater for lots of cases key presses will not, it may be less code. Depends on how you want your "notepad" to work.


  • Lifetime Qt Champion

    @stan09 I've added an example to my github.


  • Lifetime Qt Champion

    @JonB I still think handling this in the keyPressEvent handler is better, as you manipulate the char before it is inserted. And it's not much code, really:

    void TextEditor::keyPressEvent(QKeyEvent *e)
    {
        QChar lastChar = document()->characterAt(textCursor().position() - 1);
        QChar secondLastChar = document()->characterAt(textCursor().position() - 2);
    
        // If we are at the beginning of text, start a new line,
        // or start a new sentence, include an uppercase letter
        if (textCursor().atStart()
                || lastChar == QChar::ParagraphSeparator
                || lastChar == QChar::LineSeparator
                || (lastChar == QChar::Space && secondLastChar == '.')) {
            QKeyEvent event(e->type(), e->key(), e->modifiers() | Qt::ShiftModifier,
                            e->text().toUpper(), e->isAutoRepeat(), ushort(e->count()));
    
            QPlainTextEdit::keyPressEvent(&event);
            return;
        }
    
        QPlainTextEdit::keyPressEvent(e);
    }
    


  • @aha_1980
    Yes, that is fine. But most of your code is spent looking at the document state instead of prior key presses, which is my point. Originally you talked about "remember the last two keys that were pressed", you're not doing that now.

    Obviously the key press way of doing things doesn't go anywhere toward capitalising sentences in an arbitrary piece of existing text put into a QTextEdit. It depends what the OP wants his editor to do.

    In your code, if the first char I type in is a digit from the keys which have a punctuation character on the Shift of the key, what happens? This whole business of shift-modifier-on-a-key-press in order to guarantee an upper-case letter seems dubious to me....! Oh, and BTW: personally I always type two spaces after a period and before the first character of the next sentence, and I'm not totally alone. You'll have to start changing your code to accommodate me! Which is why my first inclination was to do it all via text changed and regular expressions. But probably not what the OP has in mind :)


  • Lifetime Qt Champion

    @JonB

    personally I always type two spaces after a period and

    Which is wrong. There is a DIN norm for machine typing which regulates that.

    Anyway, such cases can be covered with slightly more code.

    But how would you do that with textChanged in a simpler way?



  • @aha_1980

    Which is wrong.

    I beg your pardon!?

    There is a DIN norm for machine typing which regulates that.

    Wot?


  • Lifetime Qt Champion

    @jonb said in how to uppercase first letter of sentense in QTextEdit:

    @aha_1980

    Which is wrong.

    I beg your pardon!?

    Ok, sorry. Maybe I was too harsh. You can write as many spaces as you like.

    Should also be no big deal to handle this in code.

    There is a DIN norm for machine typing which regulates that.

    Wot?

    Germany has standards for everything.

    Still, you claim you can do better without keyPressEvent. I'm waiting for the proof :)

    Regards



  • @aha_1980
    Hi aha, you & I have always gotten on fine, I was a bit shocked by the tone of your admonition! I had not realised you are German. In England things are a bit different. If we want to type 2 spaces, or no spaces, or anything else, it's our keyboard, we don't expect the Government to dictate! This is why we voted to leave the EU, so that we can type spaces as we please ;-)

    You will note I did not say the way I mentioned is "better". It's just how I thought of it. As I said it totally depends on how the OP wants things to behave. The key press approach is a bit like a "typewriter" to me, I was thinking more of a "word processor" adjusting all text in a blob.

    I think of things like: at first I type:

    Hello world.goodbye world.
    

    I accidentally missed typing the space after the .. So I go back and put the space in:

    Hello world. goodbye world.
    

    You are not going to capitalise the g. You also have quite a bit more work to do to recognise other sentence-ending punctuations than .. Also, do all languages work by the capital letter you want is always the key you pressed plus Shift? I don't know, I thought some would have more complex rules than that, alternative capital letters or not necessarily just via Shift, etc.

    The way I thought of it was to write a regular expression (or similar) to do all capitalization over the complete text, as a generic function (which could be used from anywhere). Then something like:

    def textEdit_textChanged(self):  # or textEdit_textEdited, depending on what you want
        newText = capitalize_via_regular_expression(self.textEdit.text())
        if newText != oldText:
            self.textEdit.setText(newText)
    

    I only change the text when it does need changing, which is not very often per keystroke, but I do admit I run the reg ex once per key stroke. OK if it's small, not so good if you're typing in the complete works of Shakespeare!

    As I said, I don't claim it's "better", only that it's "different" from the key press approach. Pros & cons to each. Perhaps I should never have brought it up! You are probably right and the OP had the "typewriter" approach in mind for desired behaviour....

    Freundliche Gruesse



  • @JonB said in how to uppercase first letter of sentense in QTextEdit:

    If we want to type 2 spaces, or no spaces, or anything else, it's our keyboard, we don't expect the Government to dictate! This is why we voted to leave the EU, so that we can type spaces as we please ;-)

    I think, not using spaces after a period is concidered wrong everywhere (or at least not very professional) :) Even if you drive on the left side of the road :-)
    You wont get fined in Germany for not using spaces after a period in your text document :)

    Most (simple) programs I know, will capitalise the next letter after typing a dot AND a space. Can be very annoying, if you dont want a capital letter.
    If you move the cursor or delete some letters in between, this doesnt work anymore (but these simple programs dont care :) ).

    Unless the OP wants to go for a text correction software (like MS Word) it should be fine.



  • @pl45m4
    We are English. Along with soccer, rugby & cricket, we invented spaces, and capital letters. So we can do with them as we like ;-)

    You wont get fined in Germany for not using spaces after a period in your text document :)

    Maybe, but you will get fined for crossing the road when the light is not right for pedestrians, or hanging your washing outside.

    As I said, you are doubtless correct and the OP does want a key stroke approach.


  • Moderators

    @jonb said in how to uppercase first letter of sentense in QTextEdit:

    Maybe, but you will get fined for crossing the road when the light is not right for pedestrians

    That's true for almost everywhere except the UK, not only Germany.


Log in to reply