Russian Qt Forum
Сентябрь 30, 2024, 06:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QTextEdit - как показать невидимые символы (пробелы, табы, переводы строк)  (Прочитано 12719 раз)
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« : Июнь 16, 2009, 21:33 »

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


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

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

Собираю информацию по крупицам
http://webhamster.ru
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #1 : Июнь 17, 2009, 21:11 »

Таки никто не знает?

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

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

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

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

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


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

Записан

Собираю информацию по крупицам
http://webhamster.ru
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #2 : Июнь 17, 2009, 21:20 »

глянь исходники... сдается мне надо paintEvent переопределять
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #3 : Июнь 17, 2009, 21:36 »

глянь исходники... сдается мне надо paintEvent переопределять

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

Собираю информацию по крупицам
http://webhamster.ru
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Июнь 17, 2009, 22:32 »

я к тому что просто можно скопировать код родной отрисовки и дописать свой код (то бишь не перерисовывать а именно рисовать)
Записан
spectre71
Гость
« Ответ #5 : Июнь 17, 2009, 23:09 »

Если ничего не откопаешь готового в QTextDocument, QTextFormat, ... ...
То можно наследовать QTextDocument и сделать свое форматирование.
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #6 : Июнь 17, 2009, 23:13 »

Ну я уже посмотрел, как в Kate отрисовка табов сделана.

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

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

Собираю информацию по крупицам
http://webhamster.ru
mugabe
Гость
« Ответ #7 : Июнь 18, 2009, 07:28 »

я к тому что просто можно скопировать код родной отрисовки и дописать свой код (то бишь не перерисовывать а именно рисовать)
"просто скопировать" на самом деле не очень просто. Там оооочень много спрятано в QTextEdit_private, к которому у наследника нет доступа (хоть его и можно получить).
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #8 : Июнь 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() );
}

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

Собираю информацию по крупицам
http://webhamster.ru
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #9 : Июнь 18, 2009, 14:55 »

Блин, ну видел же, что есть у какого-то объекта, толи у QTextCursor, толи у QTextDocument, метод типа isVisible()... Как-то определялось - скрылся курсор за пределы области редактирования или нет... Щас ищу - не могу найти.
Записан

Собираю информацию по крупицам
http://webhamster.ru
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #10 : Июнь 18, 2009, 15:35 »

Ага, нашел что я видел

void QTextEdit::ensureCursorVisible ()

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

Собираю информацию по крупицам
http://webhamster.ru
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #11 : Июнь 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 на начало  видимого текста, в интернетах информации не нашел.
Записан

Собираю информацию по крупицам
http://webhamster.ru
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.121 секунд. Запросов: 23.