Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: xintrea от Июнь 16, 2009, 21:33



Название: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 16, 2009, 21:33
Здравствуйте!


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

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


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 17, 2009, 21:11
Таки никто не знает?

Я смутно представляю как вообще работает QTextEdit, и как достучаться до отрисовки глифов.

Поэтому вот такой путь хочу попробовать. Разобъём задачу на этапы. Для простоты примем, что нам поверх пробелов надо рисовать точечки.

1. Надо пробежать по видимой области текста, и выдернуть все позиции курсора, где есть пробелы.
Как это сделать?

2. Преобразовать позиции курсора в координаты.
Как это сделать?

3. По полученным координатам с каким-то смещением нарисовать точечки. С этим вопросов нет.


Что можно сказать по пункту 1 и 2? Реально ли такую инфу вытянуть из QTextEdit?



Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: Авварон от Июнь 17, 2009, 21:20
глянь исходники... сдается мне надо paintEvent переопределять


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 17, 2009, 21:36
глянь исходники... сдается мне надо paintEvent переопределять

Это когда пункт 3 буду делать. Сейчас непонятки с пунктом 1 и 2.


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: Авварон от Июнь 17, 2009, 22:32
я к тому что просто можно скопировать код родной отрисовки и дописать свой код (то бишь не перерисовывать а именно рисовать)


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: spectre71 от Июнь 17, 2009, 23:09
Если ничего не откопаешь готового в QTextDocument, QTextFormat, ... ...
То можно наследовать QTextDocument и сделать свое форматирование.


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 17, 2009, 23:13
Ну я уже посмотрел, как в Kate отрисовка табов сделана.

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

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


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: mugabe от Июнь 18, 2009, 07:28
я к тому что просто можно скопировать код родной отрисовки и дописать свой код (то бишь не перерисовывать а именно рисовать)
"просто скопировать" на самом деле не очень просто. Там оооочень много спрятано в QTextEdit_private, к которому у наследника нет доступа (хоть его и можно получить).


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 18, 2009, 12:30
Вот посоветовали такой код, довольно просто, и почти то что нужно

Код:
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() );
}

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


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 18, 2009, 14:55
Блин, ну видел же, что есть у какого-то объекта, толи у QTextCursor, толи у QTextDocument, метод типа isVisible()... Как-то определялось - скрылся курсор за пределы области редактирования или нет... Щас ищу - не могу найти.


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 18, 2009, 15:35
Ага, нашел что я видел

void QTextEdit::ensureCursorVisible ()

но этот метод именно области редактирования, а не курсора. И он ничего не возвращает, а выполняет действие - переносит прокрутку так, чтобы курсор становился виден...


Название: Re: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)
Отправлено: xintrea от Июнь 18, 2009, 23:31
В общем, лазил-лазил по документации, и метода, который бы устанавливал курсор на начало видимой области текста не нашел.

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

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

Код:
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 на начало  видимого текста, в интернетах информации не нашел.