PDA

View Full Version : QTextCursor and beginEditBlock



ecir.hana
5th March 2013, 18:06
Hello,

I have some text in QPlainTextEdit, where every line starts with 10 spaces:


// example:

line1
line2
line3
line4

Then, I select few lines and in a loop I want to remove first two spaces from all the selected lines:


// finding the startBlock and endBlock (+1)

cursor.beginEditBlock();
for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
cursor.setPosition(block.position());
cursor.setPosition(block.position() + 2, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
}
cursor.endEditBlock();

The problem is that the code above “damages” the last selected line – as if it removed some kind of end-of-line marker – when I want to jump to the end of last line the cursor moves to the line below it, between first and second character. Even the selection does not show up properly after the edit – all the lines but the last one have selection indicator expanded to the right window edge and the last line has the indicator only as wide as the line.


// after removing the first two characters:

line1 < 1. selected lines, run the code
line2 <
line3 < < 2. here I jump to end of line
| line4

^ 3. cursor appears here

When I remove `beginEditBlock()` and `endEditBlock()` everything works fine.

Please, does anyone know why is this happening?

wysota
6th March 2013, 11:07
Please prepare a minimal compilable example reproducing the problem.

ecir.hana
6th March 2013, 18:28
Please find the example here: https://bugreports.qt-project.org/browse/QTBUG-30051

wysota
6th March 2013, 22:25
This works correctly for me:


#include <QtWidgets>

int main(int argc, char **argv) {
QApplication app(argc, argv);
QPlainTextEdit edit;
edit.insertPlainText(" aaa\n aaa\n aaa\n aaa");
QTextBlock block = edit.document()->findBlock(0);
QTextCursor cursor = edit.textCursor();
cursor.beginEditBlock();
for (int i = 0; i < 3; i++) {
cursor.setPosition(block.position());
cursor.setPosition(block.position() + 2, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
block = block.next();
}
cursor.endEditBlock();
edit.show();
return app.exec();
}

ecir.hana
6th March 2013, 23:20
Thank you for the reply!

Yes, it works - but I don't understand...how is it different from the example I wrote? Does the example work for you?

The problem is, I would like the removing to be trigged by shortcut, not sure how to translate your code because I'll basically end up with what I already have, no? Sorry, I'm really confused why your code works and mine does not.

wysota
6th March 2013, 23:35
The only difference I can see between your code and mine is that in my case the code is ran before the widget is first shown on screen (thus before the document is first laid out)

ecir.hana
6th March 2013, 23:43
Hmm....exactly. That's really unfortunate as I need to run the code after the widget is drawn. Please, do you have any idea why is this happening?

wysota
6th March 2013, 23:47
We have no idea yet what is happening. You didn't verify that my code breaks when you first show the widget (and process its events) and then modify content.

ecir.hana
7th March 2013, 00:07
You didn't verify that my code breaks when you first show the widget (and process its events) and then modify content.

It breaks. (when I move "edit.show();" somewhere above "cursor.beginEditBlock();", that is...)

wysota
7th March 2013, 00:11
show() only schedules the widget for display. It does not display it. You need to process events first. Either way, if it breaks then maybe something is wrong with the document layout engine.

ecir.hana
7th March 2013, 00:23
I'm sorry I'm not sure I understand - I'm very new to Qt. Do you mean something like:


#include "mainwindow.h"
#include <QtWidgets>

int main(int argc, char **argv) {
QApplication app(argc, argv);
QPlainTextEdit edit;
edit.insertPlainText(" aaa\n aaa\n aaa\n aaa");
edit.show();

app.processEvents();

QTextBlock block = edit.document()->findBlock(0);
QTextCursor cursor = edit.textCursor();
cursor.beginEditBlock();
for (int i = 0; i < 3; i++) {
cursor.setPosition(block.position());
cursor.setPosition(block.position() + 2, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
block = block.next();
}
cursor.endEditBlock();

return app.exec();
}


Also, the code I posted processes all the events and then modifies the code, is this correct?

wysota
7th March 2013, 00:55
I don't see how beginEditBlock() could break anything since all it does is to increment two internal counters. endEditBlock() correctly decrements the one that needs it.

ecir.hana
8th March 2013, 15:23
I don't see how beginEditBlock() could break anything

The code I posted, does it work for you?

norobro
8th March 2013, 17:48
Try your code with a QTextEdit.

ecir.hana
8th March 2013, 17:53
In QTextEdit it works. But it would be really great if it worked in QPlainTextEdit too...

norobro
8th March 2013, 18:04
But it would be really great if it worked in QPlainTextEdit too...Why so? I'm interested because another poster said the same thing (link (http://www.qtcentre.org/threads/53117-Wacky-QScrollBar-behaviour-setSliderPosition-vs-sliderPosition?highlight=)) about a scrolling problem he was having with QPlainTextEdit.

ecir.hana
13th March 2013, 13:14
Why so?

Well...because it seems it's a bug and because QPlainTextEdit si faster than QTextEdit.