Пользовательские области текста (кода) в 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 г.).