QTextEdit delete whole line at given position - c++

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?

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.

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

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.

Related

clearing the output stream c++

Hello I'm trying to build a function grapher on the terminal in c++. I want that every time a new function is added the output will be cleared and the new frame will take its place.
I've tried to do system("clear") but I don't want all the terminal to be cleared and only the output stream. I've also thought about printing '\b' a lot of times but that seems inefficient.
I would also like to know how to delete 1 line.
You may try to work with console code.
Console code about cursor
There are two solution.
Here is some C style code, just to demonstate the idea easier, you may convert it into C++ style.
Clear content
//Clear content after (x,y)
printf("\033[%d,%dH\033[J",y,x);
//x the column number,y the row number
Overwrite the content
//Goto (x,y) then print the next frame, it should overwrite the old content
printf("\033[%d,%dH",y,x);
...
//your code to output the next frame

Qt - how to detect line count increase after word wrapping?

I'm using a QPlainTextEdit control with word-wrapping active and I'm wondering how can I detect, in order to update a line counter, when a block of text gets wrapped (causing the number of lines to be incremented).
The underlying QTextDocument has a signal to detect when the block count changes, but not the corresponding one for line count changes.
Is it possible to detect word-wrapping and line count increase for a QTextDocument?
It's a little bit late but perhaps my answer can help somebody.
I had almost the same need in my company and I solved it like this:
// This example show how to get the visual number of lines
QPlainTextEdit *pte = new QPlainTextEdit();
pte->setAttribute(Qt::WA_DontShowOnScreen);
pte->show();
pte->setFixedWidth(50);
pte->setPlainText("Hello world!");
/* The next line return the number of necessary line
to display the text "Hello World!" with width of 50px */
int lineCount = pte->document()->documentLayout()->documentSize().height();
Best regards
I solved by using QAbstractTextDocument's signal documentSizeChanged:
void QAbstractTextDocumentLayout::documentSizeChanged ( const QSizeF &
newSize ) [signal]
This signal is emitted when the size of the
document layout changes to newSize. Subclasses of
QAbstractTextDocumentLayout should emit this signal when the
document's entire layout size changes. This signal is useful for
widgets that display text documents since it enables them to update
their scroll bars correctly.
I know the size of my font and getting the precise size of the new underlying document allowed me to count the lines (wrapped or not) of my text document.

Aligning text in QTextEdit?

If I have a QTextEdit box, how can I align different pieces of text within the box in different ways? For example, I would like to have one sentence be aligned-left, and the next sentence in the box be aligned-right. Is this possible? If not, how might I achieve this effect in Qt?
As documentation said:
void QTextEdit::setAlignment(Qt::Alignment a) [slot]
Sets the alignment of the current paragraph to a. Valid alignments are Qt::AlignLeft, Qt::AlignRight, Qt::AlignJustify and Qt::AlignCenter (which centers horizontally).
Link: http://qt-project.org/doc/qt-5/qtextedit.html#setAlignment
So as you can see you should provide some alignment to each paragraph.
Little example:
QTextCursor cursor = ui->textEdit->textCursor();
QTextBlockFormat textBlockFormat = cursor.blockFormat();
textBlockFormat.setAlignment(Qt::AlignRight);//or another alignment
cursor.mergeBlockFormat(textBlockFormat);
ui->textEdit->setTextCursor(cursor);
Which result I get on my computer?
Or something closer to your question:
ui->textEdit->clear();
ui->textEdit->append("example");
ui->textEdit->append("example");
QTextCursor cursor = ui->textEdit->textCursor();
QTextBlockFormat textBlockFormat = cursor.blockFormat();
textBlockFormat.setAlignment(Qt::AlignRight);
cursor.mergeBlockFormat(textBlockFormat);
ui->textEdit->setTextCursor(cursor);
ui->textEdit->append("example");
cursor = ui->textEdit->textCursor();
textBlockFormat = cursor.blockFormat();
textBlockFormat.setAlignment(Qt::AlignCenter);
cursor.mergeBlockFormat(textBlockFormat);
ui->textEdit->setTextCursor(cursor);
Result:
To left align to a textbox "TerminalOutput":
string Wibble="wibble";
TerminalOutput->append(QString::fromStdString(Wibble));
TerminalOutput->setAlignment(Qt::AlignLeft);
To right align to a textbox:
string Wobble="wobble";
TerminalOutput->append(QString::fromStdString(Wobble));
TerminalOutput->setAlignment(Qt::AlignRight);
Now, sometimes, and this happens with Kosovan's answer too, the alignment in my code sets the previous line instead of the current. This is inexplicable to me. I cannot work out why this is. If anyone knows why this is, please leave a comment because it's driving me nuts.
Edit, I found the problem. So the alignment works fine, until you select some text with the cursor. The instant you do that, the alignment stops aligning the previous line and then decides to affect the following line instead of the previous and this affects all other append formats henceforth. In fact clicking anywhere inside the textbox, will do this, it must be that it's interfering with qt's internal notion of cursor position.
I fixed this problem by doing the following before appending to the textbox:
QTextCursor newCursor = TerminalOutput->textCursor();
newCursor.movePosition(QTextCursor::End);
TerminalOutput->setTextCursor(newCursor);
And what that does is just moves the cursor to the end of the textbuffer so that when you append, it clears out any cursor position of a user clicking anywhere within the textbox, and this solves my strange little problem.

Is there a way to set the console height(in lines)?

Is it possible to set how many lines the console will print before it starts to erase the top ones? For example, is it possible to set it to 3 and only make the last 3 lines be visible? So:
std::cout<<"line 1!"<<std::endl;
std::cout<<"line 2!"<<std::endl;
std::cout<<"line 3!"<<std::endl;
std::cout<<"line 4!"<<std::endl;
system("pause");
Would output:
line 3!
line 4!
Press any key to continue...
^without creating a scroll bar on the side.
I've been trying to use Console::BufferHeight but I can't seem to get it to work. This is the only thing I've been able to find that seems to be close to what I want to do: http://msdn.microsoft.com/en-us/library/system.console.bufferheight.aspx But It just shows how to read it, not how to set the size. And for some reason typing just std::cout<<System::Console::BufferHeight; gives me scope errors. Any help would be greatly appreciated. Thanks!
I think you want this:
SetConsoleWindowInfo
Example,
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT rect = {0,0, 100, 100};
SetConsoleWindowInfo(hConsole, TRUE, &rect)
Have a look at these as well (experiment with them):
SetConsoleScreenBufferSize()
SetConsoleScreenBufferInfoEx
There is an example on MSDN here.
Im new to programming also, but I tried:
while(!cin.get())
{
}
and it worked,try to place it in the bottom of the code. It will work wonders on your console!
Try changing its position (put it in the middle of the code)
I'd suggest keeping the lines yourself, in a quick class, say that cycles where to put the next line by using an iterator that is always set to point at the next line to be input into.
Next, use FillConsoleOutputCharacter() to print blanks over the lines you previously had printed there.
Then, use SetConsoleCursorPosition() to four(or however many lines you wanted) lines above where you want your input to start, and output each line in you cycle, starting at the one after your iterator. This prints all the lines in order from eldest to youngest.It's been a while, so my knowledge of C++ is kinda hazy, but this should be pretty simple with the standard library and win32 library.

Undo a newline (\n) printed to command line

printf("Error %d\n", 1);
printf("\nStatus: %d%%", 50);
prints
Error 1
Status: 50%
In this set up, is there any chance to insert Error 2\n between Error 1\n and \nStatus: 50%. I understand that \r and \b can be used to change printed text in the same line (e.g., if there is a single \n between Error 1 and Status: 50%), but can I change text in a previous line?
Thanks!
What #Ryan said.
Explanation why: stdout is some abstract stream that doesn't have to be the terminal. It may be a file, a pipe, a socket, a printer, a text to speech device or whatever. In many cases there is no sense to what you asked to do. Hence you need some library that works with the terminal specifically.
Sorry, you cannot.
But you may issue system calls to clear the whole screen instead, like system("clear") (OS-dependent).
Or use ncurses just as Kos mentioned in the comment.
You could use ANSI Escapesequences to move your "cursor" one line up:
void cursorOnLineUp(void) { printf("\033[1A"); }
Or set it to a specific position:
void setCursor(int column, int row) { printf("\033[%d;%dH", row, column) }
Haven't tried it for C++, but succesfully used it for a simple game in ANSI-C!