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

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

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

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


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

QTextObject является

базовый класс для различных видов объектов, которые могут группировать части 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)

4

Решение

Я обнаружил, что реализация этого возможна с использованием 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 г.).

4

Другие решения

Других решений пока нет …