Пользовательские области текста (кода) в QTextEdit

Я заинтересован в создании типа текстового объекта (наследующего QTextObjectInterface), который ведет себя как область кода:

  • отличительный фон
  • граница
  • шрифт фиксированной ширины
  • редактируемый контент
  • экземпляры должны быть идентифицируемыми для кода, чтобы контент внутри них мог быть извлечен (отделить код от окружающего контента)
  • сохранение / загрузка (из обычных html-файлов)
  • подсветка синтаксиса была бы плюсом, но на самом деле не требуется

Другие области документа должны вести себя обычным образом (редактируемые свойства шрифта, редактируемые цвета и т. Д.).


Qt предоставляет пример для реализации пользовательских текстовых объектов с QTextEdit. Это выглядит как сложный путь, поскольку новый текстовый объект не может использовать существующую инфраструктуру внутри QTextEdit / QTextDocument.

QTextObject is

базовый класс для различных типов объектов, которые могут группировать части QTextDocument вместе

так что наследование может быть выбором, но ни его исходные файлы в пакете Qt SDK, ни поиск в Google не содержат полезной информации.

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


В простом HTML-файле все это (кроме подсветки синтаксиса) будет легко. QTextEdit принимает html в качестве входных данных и может экспортировать html, но структура теряется в процессе.

<code class="code-sample">
  int i = 0;
</code>

Кстати, QWebView только для чтения. Он рекламирует, что:

Части документов HTML можно редактировать, например, с помощью атрибута contenteditable в элементах HTML.


Могут быть другие платформы, где это легко доступно, но текстовый редактор нужно использовать внутри Qt Creator как плагин, поэтому использование Qt Framework имеет смысл.

Итог: как реализовать области кода в виджете QTextEdit?


Более поздние правки:

  • используя Qt sdk из транка (идентифицирует себя как 4.8.4)
  • Qt Creator из транка (Qt Creator 2.6.81)

1 ответ

Решение

Я обнаружил, что реализация этого возможна с использованием QTextEdit / QTextDocument. Самая простая реализация, о которой я могу думать, представлена ​​в этом ответе для справки будущего искателя.

Обратите внимание, что сохранение / загрузку необходимо настроить как обычный.toHtml() не сохранит необходимую информацию.

Вставить блок кода просто:

QTextFrame * frame;

frame = cursor.insertFrame( code_block_format_ );
connect( frame, SIGNAL( destroyed() ),
  this, SLOT( codeBlockDeleted() ) );
code_blocks_.append( frame );

обратите внимание на две переменные, которые вы можете сохранить в классе:

QTextFrameFormat code_block_format_;
QList<const QTextFrame*> code_blocks_;

Нам нужен формат кадра, чтобы он был последовательным и отличительным. Это может быть инициализировано в конструкторе что-то вроде:

code_block_format_.setBackground( QBrush( Qt::yellow ) );
code_block_format_.setBorder( 1 );
code_block_format_.setBorderStyle( QTextFrameFormat::BorderStyle_Inset);
code_block_format_.setMargin( 10 );
code_block_format_.setPadding( 4 );

Нам нужен список, чтобы мы могли определить, является ли определенный кадр кодовым полем или нет. Поскольку все объекты, наследующие QTextObject, должны быть созданы с помощью QTextDocument::createObject(), мы не можем просто создать подкласс QTextFrame (на самом деле я думаю, что можем, но пока не уверены).

Теперь отделение кода от остального можно сделать обычным способом:

for ( it = frame->begin(); !(it.atEnd()); ++it ) {
  child_frame = it.currentFrame();
  child_block = it.currentBlock();
  if ( child_frame != NULL )
  {
    if ( code_blocks_.contains( frame ) )
    {
      /* ... */
    }
  }
} /* for ( it = frame->begin(); !(it.atEnd()); ++it ) */

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

Если вы заинтересованы в полной реализации, ознакомьтесь с репозиторием git (работа продолжается, ноябрь 2012 г.).

Другие вопросы по тегам