Search code examples
c++qtqtexteditqtextcursor

How to make QTextCursor::WordUnderCursor include more characters or larger words


I'm trying to show a tooltip when the cursor is over a keyword in a text editor using:

QTextCursor cursor = cursorForPosition(pos);
cursor.select(QTextCursor::WordUnderCursor);

This works well, but the definition of a word does not fit my needs. For example, the keyword \abcde is recognized as 2 words, \ and abcde. Similarly, the word a1:2 is recognized in three parts a1, : and 1.

Basically, what I'd like is to change the behavior, such as a word is defined as a set of characters separated by space.

I tried QTextCursor::BlockUnderCursor, but it does the same as QTextCursor::LineUnderCursor and returns the entire line.


Solution

  • Here's a way to select words separated by a space when a text cursor's position changes.

    It basically works this way:

    • Check if the current cursor is selecting (QTextCursor::anchor and QTextCursor::position have different values), and set the custom cursor's position accordingly.
    • Go forward until you reach the end or a space.
    • Store the last position reached.
    • Go back until you reach the start or a space.
    • Select from where the cursor stopped until the position previously stored as the end.
    • The result is the fetched selection.
    void Form::on_textEdit_cursorPositionChanged()
    {
        //prevent infinite loop in case text is added manually at start
        if(textCursor().position()<0)
                return;
    
        QTextCursor cursor(ui->textEdit->textCursor());
        int end;
    
        //prevent cursor from being anchored when the normal cursor is selecting
        if(ui->textEdit->textCursor().anchor()!=ui->textEdit->textCursor().position())
        {
            cursor.setPosition(ui->textEdit->textCursor().position());
        }
    
        //I'm checking for new line using QChar(8233)
        //you might have to change that depending on your platform
        while(!cursor.atEnd() &&
              (ui->textEdit->document()->characterAt(cursor.position())!=' ' && ui->textEdit->document()->characterAt(cursor.position())!=QChar(8233)))
        {
            cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor);
        }
    
        end=cursor.position();
    
        while(!cursor.atStart() &&
              (ui->textEdit->document()->characterAt(cursor.position()-1)!=' ' && ui->textEdit->document()->characterAt(cursor.position()-1)!=QChar(8233)))
        {
            cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::MoveAnchor);
        }
    
        cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor,end-cursor.position());
    
        QString result = cursor.selectedText();
    }
    

    Demonstration:

    Custom cursor at work