Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: xintrea от Февраль 18, 2015, 22:48



Название: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: xintrea от Февраль 18, 2015, 22:48
В моем редакторе, основанном на QTextEdit, необходимо сделать кнопку очистки форматирования выделенного текста.

Проблема в том, что setBlockFormat(), вопреки документации, применяет свое форматирование только для первого абзаца в выделенном тексте. А остальные абзацы не трогает. Причем, делает это как-то выборочно - некоторые виды форматирования применяет для всего выделенного текста, некоторые - только для первого абзаца в выделенном тексте.

Вот например, следующий код должен установить top и bottom отступ в 50 pix. И должен сделать это для всех абзацев в выделенном тексте, ибо "Sets the block format of the current block (or all blocks that are contained in the selection) to format."

Код:
   QTextEdit textArea;

   ...

   QTextBlockFormat format;

   // Убираются отступы
   format.setLeftMargin(0);
   format.setRightMargin(0);
   format.setTopMargin(50); // 50 - для отладки, чтобы было видно обработку абзаца
   format.setBottomMargin(50);
   format.setAlignment(Qt::AlignLeft);

   textArea->textCursor().setBlockFormat(format);

Однако, на деле, вертикальные отступы в 50 pix устанавливаются только первому абзацу (когда выбрали, например мышкой, сразу три абзаца). А нужно, чтобы отступы в 50 pix устанавливались всем абзацам.

Я решил тогда пробегать все блоки, которые содержатся в выделенном мышкой фрагменте. Сделал так:

Код:
   QTextCursor cursor(textArea->textCursor());
   for (QTextBlock::iterator it = cursor.block().begin(); !(it.atEnd()); ++it)
   {
       qDebug() << "Block iterator position: " << it.fragment().position() << " Fragment len: " << it.fragment().length();

       QTextCursor tempCursor = cursor;
       tempCursor.setPosition(it.fragment().position());
       tempCursor.setPosition(it.fragment().position() + it.fragment().length(), QTextCursor::KeepAnchor);
       tempCursor.setBlockFormat(format);
   }

И в отладке вижу, что даже если выделено несколько абзацев (на ~300 символов), в итераторе пробегается только один абзац:

Код:
Block iterator position:  3519  Fragment len:  35

Вопрос. Как же пробежать все абзацы в выделении и применить им нужное форматирование?


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: gil9red от Февраль 19, 2015, 07:32
Делал как то редактор, и в нем очищение от форматирования делал с помощью: editor->setCurrentCharFormat( QTextCharFormat() );


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: Swa от Февраль 19, 2015, 10:05
У меня работает этот код, формат присваивается всем выделенным абзацам.
Может, проблема где-то в другом месте?


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: xintrea от Февраль 19, 2015, 15:57
Делал как то редактор, и в нем очищение от форматирования делал с помощью: editor->setCurrentCharFormat( QTextCharFormat() );

Этот код рабочий, но у него есть побочный эффект: если в выделение попала картинка, она будет удалена.

А ведь нам нужно только очищать форматирование.


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: xintrea от Февраль 19, 2015, 16:10
У меня работает этот код, формат присваивается всем выделенным абзацам.
Может, проблема где-то в другом месте?

Да, сделал минимальный пример, проблема оказалась дальше.

Чтобы гарантированно удалить все форматирование, заданное через style="...", я выдергиваю HTML-код выделенного элемента, прочищаю его от атрибутов style, и вставляю обратно:

Код:
 // Удаление какого-либо форматирования стилем
 QString htmlCode=textArea->textCursor().selection().toHtml();
 qDebug() << "Before remove style: " << htmlCode;

 // В регулярных выражениях Qt кванторы по-умолчанию жадные (greedy)
 // Поэтому напрямую регвыру указывается что кванторы должны быть ленивые
 QRegExp replace_expression("style=\".*\"");
 replace_expression.setMinimal(true);

 htmlCode.replace(replace_expression, "");

 qDebug() << "After remove style: " << htmlCode;

 QString currStyleSheet=textArea->document()->defaultStyleSheet();
 textArea->document()->setDefaultStyleSheet(" ");

 textArea->textCursor().removeSelectedText();
 textArea->textCursor().insertHtml(htmlCode);

 textArea->document()->setDefaultStyleSheet(currStyleSheet);

Проблема в том, что Qt за каким-то хером, несмотря на тот HTML, который ему передан для вставки, форматирует первую строку по какому-то ему ведомому алгоритму.

Я наблюдаю этот глюк и если вставить просто текст из браузера - первая строка в момент вставки будет как-то по-другому отформатирована даже в нативном QTextEdit, попробуйте например взять кусок разноцветного исходника отсюда:

http://www.qtcentre.org/threads/40001-How-to-change-current-line-format-in-QTextEdit

и вставить в QTextEdit. Первая строка гарантированно будет иметь более другие вертикальные отступы.

И вот с этим я никак не могу побороться. Метод setCurrentCharFormat() не подходит, так как он не только очищает формат символов, но и удаляет картинки. А мне то нужно только очищать форматирование.


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: Bepec от Февраль 19, 2015, 16:18
Мб бредово будет звучать, но там вроде идёт поведения аля "вставляемые строки имеют тот же формат, что и символ/абзац перед ними".
Просто проверьте, что будет если сначала вставить кусок текста с вашим форматированием, а потом удалить их?

PS вот это бред я написал, но а чем не попытка :D


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: kai666_73 от Февраль 20, 2015, 11:45
Мб бредово будет звучать, но там вроде идёт поведения аля "вставляемые строки имеют тот же формат, что и символ/абзац перед ними".
Просто проверьте, что будет если сначала вставить кусок текста с вашим форматированием, а потом удалить их?

PS вот это бред я написал, но а чем не попытка :D

Вовсе не бред. Только последовательность немного другая должна быть: вставить символ -> выделить его, задать форматирование -> Сделать то что изначально было необходимо -> удалить первый символ
... но костыль


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: Bepec от Февраль 20, 2015, 12:17
наличие костыля лучше чем его отсутствие. А бред - по форме изложения :D


Название: Re: QTextEdit: Применение форматирование к выделенному тексту.
Отправлено: xintrea от Февраль 20, 2015, 20:32
Делал как то редактор, и в нем очищение от форматирования делал с помощью: editor->setCurrentCharFormat( QTextCharFormat() );

Кстати, проблма не только в том, что удаляются картинки.

Еще оказалось, что в Qt 4.x не удаляется цвет текста. А в Qt 5.x - удаляется. Я проверил вначале на пятой версии, а в четвертой мне такой сюрприз.