LINUX.ORG.RU

[Qt 4.5] QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк) ?


0

0

Здравствуйте!

Хочется вот чего - в QTextEdit сделать возможным показывать пробелы (в виде точечек), табы (в виде стрелочек), переводы строк (в виде пи).

Вопрос - возможно ли такое, с какой стороны подступиться?


Ответ на: комментарий от imp

> Я думаю наследование спасёт отца русской демократии.

И какой метод переопределять нужно?

xintrea
() автор топика

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

MikeDM ★★★★★
()
Ответ на: комментарий от nu11

> поковыряй исходники КДЕшных kate/kwrite, они показывают пробелы точками.

А где этот режим включается? Что-то у меня нив kate, ни в kwrite пробелы точками не показываются, и настроек таких не нашел.

xintrea
() автор топика
Ответ на: комментарий от xintrea

> А где этот режим включается? Что-то у меня нив kate, ни в kwrite пробелы точками не показываются, и настроек таких не нашел.

Settings/configure editor/editing/show tabulators вроде бы

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от kitov

И что в QTextCharFormat можно использовать?


Я нашел только более-менее подходящее для задачи вот это

QPen QTextCharFormat::textOutline () const
Returns the pen used to draw the outlines of characters in this format.

Но это всего лишь объект, стилизующий точку рисования. Через него не вытянешь, например, координаты текущего символа (глифа), чтоб поверх что-нибудь нарисовать.

xintrea
() автор топика
Ответ на: комментарий от eXOR

> Вот и рисуй поверх то, чем ты хочешь обозначить невидимый символ.

Это не проблема. Проблема - как узнать координаты куды рисовать?

xintrea
() автор топика
Ответ на: комментарий от xintrea

QTextDocument::find(...) => QTextCursor
QTextEdit::cursorRect(QTextCursor const &) => QRect
QTextEdit::paintEvent и вперед .
Примерно так .

kitov ★★★
()
Ответ на: комментарий от nu11

> http://websvn.kde.org/

Как этой хренью пользоваться? Нужно мне заглянуть в файлы

ktexteditor/editor.h
ktexteditor/editor.cpp
ktexteditor/editorchooser.h
ktexteditor/editorchooser.cpp

где их найти?


Или нужно вытянуть kate, можно ли отдельно? Или нужно весь KDE тянуть?

xintrea
() автор топика
Ответ на: комментарий от nu11

Не, в онлайне без поиска в тысячах файлах разораться нереально.

Щас качаю куски исходников KDE 3.5.10

xintrea
() автор топика
Ответ на: комментарий от nu11

В общем анализ исходников Kate показал, что QTextEdit там и не пахло. Там область редактирования практически с нуля написана, отрисовывается всё по строкам (функция paintTextLine(). В момент отрисовки идёт посимвольный анализ, и на месте табов рисуются уголочки, если это задано в настройках.

Теперь осталось понять, реально ли механизмом наследования изменить QTextEdit так, чтоб он нужные глифы отрисовывал как мне нужно, или это невозможно впринципе.

xintrea
() автор топика
Ответ на: комментарий от xintrea

>Теперь осталось понять, реально ли механизмом наследования изменить QTextEdit так, чтоб он нужные глифы отрисовывал как мне нужно, или это невозможно впринципе.

kitov посоветовал же:

void TextEdit::paintEvent( QPaintEvent * e ) {
	QTextEdit::paintEvent( e );
	QPainter p( viewport() );
	QTextCursor cur;
	do {
		cur = document()->find( " ", cur );
		QRect rect = cursorRect( cur );
		p.drawText( QRect( rect.left() - 3, rect.top(), rect.right(), rect.bottom() ), "." );
	}
	while( !cur.isNull() );
}

summatus
()
Ответ на: комментарий от summatus

Спасибо, добрый summatus! Седни попробую.

Остался еще один вопрос - как пробегать не весь документ на предмет поиска пробелов, а только ту часть, которая видна на экране?

xintrea
() автор топика
Ответ на: комментарий от summatus

В общем, лазил-лазил по документации, и метода, который бы
устанавливал курсор на начало видимой области текста не нашел.

Но, так как мы можем для любой позиции курсора определить 
координаты курсора относительно видимой области, то применив 
метод бисекций можно достаточно быстро найти позицию курсора, 
с которой начинается видимый текст.


Получился такой код (отрисовывает точки на месте пробелов)


Код:
void EditorTextArea::paintEvent(QPaintEvent *event)
{
 // Отрисовка родительского класса
 QTextEdit::paintEvent(event);

 // Начало области поиска
 int document_start_frame_search=0;
 
 // Конец области поиска
 QTextCursor cur=textCursor();
 cur.movePosition(QTextCursor::End);
 int document_end_frame_search=cur.position();

 qDebug() << "Document lenght " << document_end_frame_search;

 int analyse_point=0;
 int start_frame_iteration_count=0;

 while(true)
 {
  // Новая проверяемая позиция курсора устанавливается в середину области поиска
  analyse_point=(document_start_frame_search+document_end_frame_search)/2;
  cur.setPosition(analyse_point);

  qDebug() << "Start " << document_start_frame_search << " End " << document_end_frame_search << " Analyse position " << analyse_point;

  // Дополнительный курсор смещается на символ влево
  QTextCursor dopcur=cur;
  bool previos_result=dopcur.movePosition(QTextCursor::PreviousCharacter);

  // Если смещаться было некуда, значит начало документа
  // и начало видимой области совпадают
  if(previos_result==false)
   {
    qDebug() << "Start document found";
    break;
   }

  QRect dopcur_rect=cursorRect(dopcur);
  QRect cur_rect=cursorRect(cur);

  // Если текущая позиция является границей начала видимой области
  if(dopcur_rect.top()<0 && cur_rect.top()>=0)
   {
    qDebug() << "Edge visible area found";
    qDebug() << "Position " << cur.position() << " Dop cur Y " << dopcur_rect.top() << " Cur Y " << cur_rect.top();
    break;
   }

  // Нужно решить куда переносить границы поиска
  // Если координаты курсора положительные, значит курсор
  // находится "ниже" начала области обзора
  if(cur_rect.top()>0)
   document_end_frame_search=analyse_point; // Нижняя граница двигается вверх
  else
   document_start_frame_search=analyse_point; // Верхняя граница двигается вниз

  // Если границы сомкнулись
  if((document_start_frame_search+1)==document_end_frame_search ||
     document_start_frame_search==document_end_frame_search)
   {
    qDebug() << "Edge eqivalent";
    cur.setPosition(document_start_frame_search);
    break;
   }

  start_frame_iteration_count++;
 }

 qDebug() << "Found vision area at position " << cur.position() << " Iterations " << start_frame_iteration_count;

 // Поверх рисуются элементы разметки
 QPainter p(viewport());
 p.setRenderHint(QPainter::Antialiasing,false);
 p.setRenderHint(QPainter::HighQualityAntialiasing,false);

 QPen pen(Qt::darkGray);
 pen.setStyle(Qt::SolidLine);
 p.setPen(pen);

 do {
  cur = document()->find( " ", cur );
  QRect rect = cursorRect( cur );
  int y=(rect.top()+rect.bottom())/2;

  // Если координаты курсора вышли за размер области обзора
  if(y>viewport()->height())break; // Дальше рисовать ненужно

  p.drawRect(rect.left()-3,y,1,1);

 }
 while( !cur.isNull() );
}

Такой метод отрисовки работает в разы быстрее "прямого" метода,
который рисует точки для всех пробелов, даже для невидимых.

Примерный расчет такой - на 5000 символов для определения начала 
области видимости текста тратится максимум 12 итераций.

Код:
Document lenght  4994
Start  0  End  4994  Analyse position  2497
Start  2497  End  4994  Analyse position  3745
Start  3745  End  4994  Analyse position  4369
Start  3745  End  4369  Analyse position  4057
Start  3745  End  4057  Analyse position  3901
Start  3745  End  3901  Analyse position  3823
Start  3745  End  3823  Analyse position  3784
Start  3784  End  3823  Analyse position  3803
Start  3803  End  3823  Analyse position  3813
Start  3813  End  3823  Analyse position  3818
Start  3818  End  3823  Analyse position  3820
Start  3818  End  3820  Analyse position  3819
Edge visible area found
Position  3819  Dop cur Y  -16  Cur Y  0
Found vision area at position  3819  Iterations  11

Незнаю, может это и велосипед получился. Но по поводу установки 
курсора в Qt на начало видимого текста, в интернетах информации 
не нашел.

xintrea
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.