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.
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 in line setTextCursor(cursor);
:
How do I search for a string in a document and not change the current position if none is found?
Based on this answer, 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? 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();
}
}
}
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);
}
}
}