10

I need to delete a specific line from QTextEdit (NoWrap option is active) manualy from the program. I found a solution which explains how to remove first line, but i wonder how can I remove whole line at specific index.

I've also found a solution here Remove a line/block from QTextEdit , but I don't know what these blocks are. Do they represent single lines or not? Should i iterate through these blocks and if i reach block at given index, then delete it?

Community
  • 1
  • 1
Michal
  • 1,955
  • 5
  • 33
  • 56
  • According to the Qt document, block = paragraph. While the title of the question you referred might be confusing, the asker did mention "*In my particular case one block = one line*". – Tay2510 Jan 07 '15 at 08:12
  • Ok, so when NoWrap option is active for lines, then block = paragraph = line, am I right? – Michal Jan 07 '15 at 08:14
  • Yes you can say that. – Tay2510 Jan 07 '15 at 08:45
  • Dead link in question. Please update or remove.(http://developer.nokia.com/community/discussion/showthread.php/203176-QTextEdit-delete-first-lines) – mattsson Jan 04 '16 at 14:36

3 Answers3

11

You can remove the line at lineNumer with :

QTextCursor cursor = textEdit->textCursor();

cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, lineNumer);
cursor.select(QTextCursor::LineUnderCursor);
cursor.removeSelectedText();
cursor.deleteChar(); // clean up new line

textEdit->setTextCursor(cursor);

Here you put the cursor at the beginning of the document, move down lineNumer times, select the specific line and remove it.

Alex Baum
  • 166
  • 9
Nejat
  • 31,784
  • 12
  • 106
  • 138
  • It would be wise to also disable the cursor for this short period, so that a button press or mouse click wouldn't interfere. The chances are small, but it might be a danger. – vsz Jan 07 '15 at 08:23
  • 2
    Nice! Though I feel `QTextCursor cursor = ui->textEdit->textCursor(); cursor.select(QTextCursor::LineUnderCursor); cursor.removeSelectedText();` is sufficient to do the job. – Tay2510 Jan 07 '15 at 08:26
  • As long as there are not multiple threads interacting with the GUI, there shouldn't be cases where the cursor could be changed in the middle of executing the sequence. Qt will process user events in the event loop – theorifice Mar 01 '17 at 21:49
3

You can do the following:

QTextEdit te;
// Three lines in the text edit
te.setText("Line 1\nLine 2\nLine 3");

const int lineToDelete = 1; // To delete the second line.
QTextBlock b = te.document()->findBlockByLineNumber(lineToDelete);
if (b.isValid()) {
    QTextCursor cursor(b);
    cursor.select(QTextCursor::BlockUnderCursor);
    cursor.removeSelectedText();
}
vahancho
  • 20,808
  • 3
  • 47
  • 55
2

I know that this question has been accepted and that it's fairly dead here, but I'm going to posit my experiences with QTextEdit as a caution to those that follow.

My problem space was similar to OP's in that I wanted to remove a single line from a text edit. I following the given solution here, improving upon it slightly, and ultimately believed that I had found success.

That success, however, was only realized while the text edit was being viewed, or if it had appeared on screen at least once throughout the course of the program. While I cannot confirm this, I believe that it has to do with cursor manipulation.

Here's a more in-depth explanation:

I desired to create a message history between a UI and the remote unit to which it was conversing. The messages would be color-coded, one for the UI's sent messages, the other for the received messages. In order to prevent a massive memory impact, the idea is to limit the number of lines to a specific amount, say 1000.

My original code was much like the accepted answer:

  • If the number of lines exceeded my setpoint, move cursor to the beginning and delete the first line.

After some time, however, I began to notice a slowdown in the runtime execution of the program. After adding debug in, I found that, so long as I had not actually viewed the location to which the text was sent, the line-limiter never actually erased the lines. The QTextEdit to which the text was sent was in a tabbed widget. This means that I had to cycle through to that tab, otherwise the algorithm wouldn't work.

Here is a working solution for my problem space:

void ScrollingEdit::append(QString text, QColor color)
{
    QString pc = QString("<body style=\"color:rgb(%1,%2,%3);\">").
        arg(color.red()).arg(color.green()).arg(color.blue());
    QString ac = QString("</body>");

    text.prepend( pc );
    text.append( ac );

    mText.append( text );

    QString delim = "</body>";

    if ( mText.count( delim ) > mMaxLine )
    {
        mText.remove(0, mText.indexOf( delim ) + delim.size() );
    }

    mEdit->clear();
    mEdit->setHtml( mText );

    QTextCursor cursor = mEdit->textCursor();

    cursor.movePosition( QTextCursor::End );

    mEdit->setTextCursor(cursor);
    mEdit->ensureCursorVisible();
}

Where mText is a member variable QString that acts as the "model" for the text edit, mMaxLine is a user-configurable int that sets the maximum number of allowable lines, and mEdit is the UI QTextEdit. Note that cursor manipulation still exists, but where it matters, which is when the user is viewing the element.

Alex Baum
  • 166
  • 9