3

I want to search in QPlainTextEdit for a string from the current cursor to the end. If nothing is found I want to continue searching from the start. Only in this stage, if nothing is found, a message will appear. This is the code:

void BasicEdit::findString(QString s, bool reverse, bool casesens, bool words) {
QTextDocument::FindFlags flag;
if (reverse) flag |= QTextDocument::FindBackward;
if (casesens) flag |= QTextDocument::FindCaseSensitively;
if (words) flag |= QTextDocument::FindWholeWords;

QTextCursor cursor = this->textCursor();

if (!find(s, flag)) {
    //nothing is found | jump to start/end
    cursor.movePosition(reverse?QTextCursor::End:QTextCursor::Start);
    setTextCursor(cursor); //!!!!!!
    if (!find(s, flag)) {
        //no match in whole document
        QMessageBox msgBox;
        msgBox.setText(tr("String not found."));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
  }
}

The problem is line setTextCursor(cursor);

  • without this line, the search does not continue from the beginning/end
  • with this line everything is fine except that when string is not found the cursor is positioned at the beginning / end of the document, and the current position in document for user is lost.

How to search for a string in a document and do not change current position if none is found?


Update

Thanks to IAmInPLS the code looks like below. I added value preservation for verticalScrollBar. Even so, there is a short flickering when nothing is found generated by: cursor.movePosition(reverse?QTextCursor::End:QTextCursor::Start);

How can we get rid of it? How can look like a professional editor? It is an idea to create another invisible QPlainTextEdit element to search in it?

void BasicEdit::findString(QString s, bool reverse, bool casesens, bool words)
{
QTextDocument::FindFlags flag;
if (reverse) flag |= QTextDocument::FindBackward;
if (casesens) flag |= QTextDocument::FindCaseSensitively;
if (words) flag |= QTextDocument::FindWholeWords;

QTextCursor cursor = this->textCursor();
// here we save the cursor position and the verticalScrollBar value
QTextCursor cursorSaved = cursor;
int scroll = verticalScrollBar()->value();

if (!find(s, flag))
{
    //nothing is found | jump to start/end
    cursor.movePosition(reverse?QTextCursor::End:QTextCursor::Start);
    setTextCursor(cursor);

    if (!find(s, flag))
    {
        // word not found : we set the cursor back to its initial position and restore verticalScrollBar value
        setTextCursor(cursorSaved);
        verticalScrollBar()->setValue(scroll);
        QMessageBox msgBox(this);
        msgBox.setText(tr("String not found."));
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setDefaultButton(QMessageBox::Ok);
        msgBox.exec();
    }
}
}
Junior
  • 507
  • 5
  • 19
  • Save the initial cursor position in the beginning and then restore it if nothing is found. – hank Jun 03 '16 at 08:49

1 Answers1

2

The idea is to keep the cursor position you have before starting to search for the word. Then, after the research, you will set the cursor back to the position you saved.

void BasicEdit::findString(QString s, bool reverse, bool casesens, bool words) 
{
    QTextDocument::FindFlags flag;
    if (reverse) flag |= QTextDocument::FindBackward;
    if (casesens) flag |= QTextDocument::FindCaseSensitively;
    if (words) flag |= QTextDocument::FindWholeWords;

    QTextCursor cursor = this->textCursor();
    // here , you save the cursor position
    QTextCursor cursorSaved = cursor;

    if (!find(s, flag)) 
    {
        //nothing is found | jump to start/end
        cursor.movePosition(reverse?QTextCursor::End:QTextCursor::Start);

        /* following line :
        - the cursor is set at the beginning/end of the document (if search is reverse or not)
        - in the next "find", if the word is found, now you will change the cursor position
        */ 
        setTextCursor(cursor);

        if (!find(s, flag)) 
        {
            //no match in whole document
            QMessageBox msgBox;
            msgBox.setText(tr("String not found."));
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setDefaultButton(QMessageBox::Ok);
            msgBox.exec();

            // word not found : we set the cursor back to its initial position
            setTextCursor(cursorSaved);
        }
    }
}
IAmInPLS
  • 4,051
  • 4
  • 24
  • 57
  • Thank you. I updated the code, but still does not look professional. We can block **verticalScrollBar** during the search to avoid flickering? Or we can use a copy of **QPlainTextEdit** to be searched in the background? – Junior Jun 03 '16 at 21:49