Gotoline in Qt Creator - c++

Well, I'm doing a Goto Line System. But it seems it doesn't work. It did before but I think I broke it.
void ScriptWindow::gotoLine()
{
int line = QInputDialog::getInteger(myEdit, "Line Number","To what line do you want to go?", 1, 1, myEdit->document()->lineCount());
QTextCursor cursor = myEdit->textCursor();
myEdit->setTextCursor(cursor);
cursor.setPosition(QTextCursor::Start, QTextCursor::MoveAnchor);
while(cursor.position() == QTextCursor::Start) {
cursor.setPosition(line - 1, QTextCursor::MoveAnchor);
}
}
Could you please tell me what am I doing wrong?

Set the cursor position to zero, move down by number of lines, and set myEdit's text cursor.
QTextCursor cursor = myEdit->textCursor();
cursor.setPosition(0);
cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line-1);
myEdit->setTextCursor(cursor);
Alternatively, find the position via the QTextDocument and then just set the position.
int pos = myEdit->document()->findBlockByLineNumber(line-1).position();
QTextCursor cursor = myEdit->textCursor();
cursor.setPosition(pos);
myEdit->setTextCursor(cursor);

Related

Reset text formatting in QTextEdit after space

Are there good solution to reset text formatting (e.g. bold) after press Space button for QTextEdit?
Example of case:
boldText notBoldText // After press Space button text is not bold anymore
For example, I can use QWidget::eventFilter(...) and check inside
if (key == Qt::Key_Space) { ... }
But it looks bad.
It's how I set formatting now:
QTextCursor cursor = textCursor();
if (!cursor.hasSelection())
return;
QTextCharFormat fmt;
fmt.setFontWeight(cursor.charFormat().font().bold() ? QFont::Normal : QFont::DemiBold);
cursor.mergeCharFormat(format);
mergeCurrentCharFormat(format);

QPlainTextEdit - searches the document to the end and again from the beginning

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();
}
}
}
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);
}
}
}

Making a QTextEdit capital

I am trying to make all text in a QTextEdit capital, but currently am failing. This is my code and it does nothing.
void MainWindow::on_actionCapital_triggered()
{
QTextCharFormat capital2;
capital2.setFontCapitalization(QFont::AllUppercase);
ui->textEdit->setCurrentCharFormat(capital2);
}
I am a java coder, so c++ is not my strong point
I also tried the following code with no success:
QFont font = ui->textEdit->font();
font.setCapitalization(QFont::AllUppercase);
ui->textEdit->setFont(font);
Can someone please point me to the right direction?
I figured it out not the most elegant solution, but it will do its job:
void MainWindow::on_actionCapital_triggered()
{
QTextCursor c = ui->textEdit->textCursor();
int current = c.position();
if(capital)
{
QTextCharFormat capital2;
capital2.setFontCapitalization(QFont::MixedCase);
ui->textEdit->selectAll();
ui->textEdit->setCurrentCharFormat(capital2);
capital = false;
}
else
{
QTextCharFormat capital2;
capital2.setFontCapitalization(QFont::AllUppercase);
ui->textEdit->selectAll();
ui->textEdit->setCurrentCharFormat(capital2);
capital = true;
}
c = ui->textEdit->textCursor();
c.setPosition(current);
c.setPosition(current, QTextCursor::KeepAnchor);
ui->textEdit->setTextCursor(c);
}
With this code you can switch between all Upper case and mixed case.
For some reason the setCurrentCharFormat only works when the text is selected.
So I had to get the current cursor position and then select all apply the FontCapitalization and then set the cursor back to where it was.

QTextEdit. How to select text manually?

There are functions like textEdit->textCursor()->selectionStart() and textEdit->textCursor()->selectionEnd(), but there are no functions setSelectionStart, setSelectionEnd.
Is there any way to select some part of text manually?
QTextCursor c = textEdit->textCursor();
c.setPosition(startPos);
c.setPosition(endPos, QTextCursor::KeepAnchor);
textEdit->setTextCursor(c);
This piece of code moves the cursor to the start position of the selection using setPosition, then moves it to the end of the selection, but leaves the selection anchor at the old position by specifying a MoveMode as the second parameter.
The last line sets the selection to be visible inside the edit control, so you should skip it if you just want to do some manipulations with the selected text.
Also, if you don't have the exact positions, movePosition is helpful: you can move the cursor in various ways, such as one word to the right or down one line.
I encountered a similar problem.
In Windows 10, there might be a bug of 'drag/move'. We use QT_NO_DRAGANDDROP as a compiler option, which makes text selection in QTextEdit not work anymore.
Solution:
void QTextEditEx::mouseMoveEvent(QMouseEvent *event)
{
QTextEdit::mouseMoveEvent(event);
if (event->buttons() & Qt::LeftButton)
{
QTextCursor cursor = textCursor();
QTextCursor endCursor = cursorForPosition(event->pos()); // key point
cursor.setPosition(pos, QTextCursor::MoveAnchor);
cursor.setPosition(endCursor.position(), QTextCursor::KeepAnchor);
setTextCursor(cursor);
}
}
void QTextEditEx::mousePressEvent(QMouseEvent *event)
{
QTextEdit::mousePressEvent(event);
if (event->buttons() & Qt::LeftButton)
{
QTextCursor cursor = cursorForPosition(event->pos());
// int pos; member variable
pos = cursor.position();
cursor.clearSelection();
setTextCursor(cursor);
}
}
reference:
Two existing answers
QTextEdit: get word under the mouse pointer?
Try to use:
QTextCursor cur = tw->textCursor();
cur.clearSelection();
tw->setTextCursor(cur);

Why does this code not highlight the search term once found?

The code below does not highlight the search term when it is found. In fact the cursor disappears from the QPlainTextEdit (called ui->Editor) after pressing the 'next' button. What's causing it?
void TextEditor::findNextInstanceOfSearchTerm()
{
QString searchTerm = this->edtFind->text();
if(this->TextDocument == NULL)
{
this->TextDocument = ui->Editor->document();
}
QTextCursor documentCursor(this->TextDocument);
documentCursor = this->TextDocument->find(searchTerm,documentCursor);
if(!documentCursor.isNull())
{
documentCursor.select(QTextCursor::WordUnderCursor);
}else
{
ui->statusbar->showMessage("\""+searchTerm+"\" could not be found",MESSAGE_DURATION);
}
}
Firstly, your code creates a new cursor at the beginning of the document each time you press the next button, so you will always search from the beginning. Secondly, you must understand that the cursor you manipulate has nothing to do with the one in your QPlainTextEdit: you manipulate a copy. If you want to impact the text edit, you must modify its cursor using setTextCursor. Here is a working solution:
void TextEditor::findNextInstanceOfSearchTerm()
{
QString searchTerm = this->edtFind->text();
if(this->TextDocument == NULL)
{
this->TextDocument = ui->Editor->document();
}
// get the current cursor
QTextCursor documentCursor = ui->Editor->textCursor();
documentCursor = this->TextDocument->find(searchTerm,documentCursor);
if(!documentCursor.isNull())
{
// needed only if you want the entire word to be selected
documentCursor.select(QTextCursor::WordUnderCursor);
// modify the text edit cursor
ui->Editor->setTextCursor(documentCursor);
}
else
{
ui->statusbar->showMessage(
"\""+searchTerm+"\" could not be found",MESSAGE_DURATION);
}
}
As a side note, you might want to know that QPlainTextEdit provides a find method, so this might be an easier way to achieve what you want:
void TextEditor::findNextInstanceOfSearchTerm()
{
QString searchTerm = this->edtFind->text();
bool found = ui->Editor->find(searchTerm);
if (found)
{
QTextCursor cursor = ui->Editor->textCursor();
cursor.select(QTextCursor::WordUnderCursor);
ui->Editor->setTextCursor(cursor);
}
else
{
// set message in status bar
}
}
Use QTextCursor::EndOfWord
Use QPlainTextEdit::setExtraSelections to select/highlight something in QPlainTextEdit
Simply you already have cursor that would highlight word, but you didn't apply it to text edit