[Предыдущая: Обработка форматированного текста] [Содержание] [Следующая: Интерфейс QTextCursor] Структура документа форматированного текста
|
Базовая структура "Верхний уровень" документа может быть населен следующим способом. Каждый документ всегда содержит корневой фрейм, который всегда содержит хотя бы один текстовый блок. Для документов с некоторым текстовым содержимым корневой фрейм обычно содержит последовательность блоков и других элементов. Последовательности фреймов и таблиц всегда разделены текстовыми блоками в документе, даже если текстовые блоки не содержат информации. Это обеспечивает то, что новые элементы всегда могут быть вставлены между существующими структурами. |
В этой главе мы взглянем на каждый из структурных элементов, используемых в документах форматированного текста, обрисуем их особенности и применение и покажем, как изучить их содержимое. Редактирование документа описано в Интерфейс QTextCursor.
Объект QTextDocument содержит всю информацию, необходимую для конструирования документов форматированного текста с целью использования с виджетом QTextEdit или в собственном редакторе. Хотя QTextEdit делает простым отображение и редактирование форматированного текста, документы могут быть так же использованы независимо от любого виджета-редактора, например:
QTextDocument *newDocument = new QTextDocument;
Или же они могут быть извлечены из существующего редактора:
QTextEdit *editor = new QTextEdit; QTextDocument *editorDocument = editor->document();
Эта гибкость позволяет приложениям обрабатывать документы форматированного текста без накладных расходов на множество виджетов-редакторов или требований хранения документов в некотором промежуточном формате.
Пустой документ содержит корневой фрейм, который содержит внутри один пустой текстовый блок. Интерфейс текстового курсора автоматически вставляет новые элементы документа в корневой фрейм и гарантирует, что он заполнен пустыми блоками, где необходимо.
Мы получаем корневой фрейм следующим способом:
QTextDocument *textDocument; QTextFrame *root = textDocument->rootFrame();
Когда перемещаемся по структуре документа, полезна начать с корневого фрейма, потому что он предоставляет доступ к всей структуре документа.
Документы форматированного текста обычно состоят из обычных элементов, таких как параграфы, фреймы, таблицы и списки. Они представлены в QTextDocument классами QTextBlock, QTextFrame, QTextTable и QTextList. В отличие от других элементов в документе, изображения представлены специально форматированными текстовыми фрагментами. Это позволяет им быть размещенными с форматированием внутри окружающего текста.
Базовые структурные строительные блоки в документах это QTextBlock и QTextFrame. Блоки в себе содержат фрагменты форматированного текста (QTextFragment), но они не влияют прямо на верхний уровень структуры документа.
Элементы, которые группируются вместе другими элементами документа, обычно подклассы QTextObject, и разбиваются на две категории: элементы, группирующие вместе текстовые блоки, подклассы QTextBlockGroup, и те, которые группируют вместе фреймы и другие элементы, подклассы QTextFrame.
Текстовые блоки обеспечиваются классом QTextBlock.
Текстовые блоки группируют вместе фрагменты текста с различными текстовыми форматами и используются для представления параграфов в документе. Каждый блок обычно содержит числовые или текстовые фрагменты с различными стилями. Фрагменты создаются, когда текст вставляется в документ и большая часть из них добавляется при редактировании документа. Документ разбивается, объединяется и удаляет фрагменты для эффективного представления различных стилей текста в блоке.
Фрагмент внутри данного блока может быть изучен, используя QTextBlock::iterator для обхода внутренней структуры блока:
QTextBlock::iterator it; for (it = currentBlock.begin(); !(it.atEnd()); ++it) { QTextFragment currentFragment = it.fragment(); if (currentFragment.isValid()) processFragment(currentFragment); } }
Блоки так же используются для представления списка элементов. В качестве результата блоки могут определять их собственные форматы символов, которые содержат информацию о декорации уровня блока, такую как тип точек, используемый для списка элементов. Форматирование для блока описано классом QTextBlockFormat и описывает такие свойства как выравнивание текста, отступы и цвет фона.
Хотя данный документ может содержать сложные структуры, как только мы получим ссылку на корректный блок в документе, мы можем перемещаться между каждым из текстовых блоков в том порядке, в котором они были написаны:
QTextBlock currentBlock = textDocument->begin(); while (currentBlock.isValid()) { processBlock(currentBlock); currentBlock = currentBlock.next(); }
Этот метод полезен, когда вы хотите извлечь только форматированный текст из документа, потому что он игнорирует фреймы, таблицы и другие типы структур.
QTextBlock предоставляет операторы сравнения, которые делают манипулирование блоками проще: operator==() и operator!=() для теста являются ли два блока одинаковыми и operator<() используется для определения какой появляется первым в документе.
Фреймы обеспечиваются классом QTextFrame.
Текстовые фреймы группируют вместе блоки текстов и дочерние фреймы, создавая структуры документов, которые больше чем параграф. Формат фрейма определяет как он отрисовывается и позиционируется на странице. Фреймы или вставляются в поток текста, или они плавают с левой или правой стороны страницы. Каждый документ содержит корневой фрейм, который содержит все другие элементы документа. В результате все фреймы, кроме корневого, имеют родительский фрейм.
Так как текстовые блоки используются для разделения других элементов документа, каждый фрейм всегда будет содержать, по крайней мере, один текстовый блок и ноль или больше дочерних фреймов. Мы можем проверить содержимое фрейма, используя QTextFrame::iterator для обхода дочерних элементов фрейма:
QTextFrame::iterator it; for (it = frame->begin(); !(it.atEnd()); ++it) { QTextFrame *childFrame = it.currentFrame(); QTextBlock childBlock = it.currentBlock(); if (childFrame) processFrame(frameElement, childFrame); else if (childBlock.isValid()) processBlock(frameElement, childBlock); }
Заметьте, что итератор выделяет и фреймы и блоки, так что необходимо проверять, на что он ссылается. Это позволяет нам перемещаться по структуре документа от фрейма к фрейму, сохраняя доступ к текстовым блокам, если потребуется. Оба класса QTextBlock::iterator и QTextFrame::iterator могут быть использованы в дополняющих друг друга путях извлечения требуемой структуры из документа.
Таблицы предоставляются классом QTextTable.
Таблицы это коллекции ячеек, которые упорядочены в строках и столбцах. Каждая ячейка таблицы это элемент документа с его собственным форматом символов, но он также может содержать другие элементы, такие как фреймы и текстовые блоки. Ячейки таблицы автоматически создаются, когда таблица сконструирована или когда дополнительная строка или столбец добавлены. Они также могут перемещаться между таблицами.
QTextTable это подкласс QTextFrame, таким образом, таблицы рассматриваются как фреймы в структуре документа. Для каждого фрейма, с которым мы сталкивается в документе, мы можем проверить является ли он таблицей, и работать с ним иначе:
QTextFrame::iterator it; for (it = frame->begin(); !(it.atEnd()); ++it) { QTextFrame *childFrame = it.currentFrame(); QTextBlock childBlock = it.currentBlock(); if (childFrame) { QTextTable *childTable = qobject_cast<QTextTable*>(childFrame); if (childTable) processTable(frameElement, childTable); else processFrame(frameElement, childFrame); } else if (childBlock.isValid()) processBlock(frameElement, childBlock); }
Ячейки внутри существующей таблицы могут быть изучены, перебором строк и столбцов.
for (int row = 0; row < table->rows(); ++row) { for (int column = 0; column < table->columns(); ++column) { QTextTableCell tableCell = table->cellAt(row, column); processTableCell(tableCell); } }
Обеспечиваются классом QTextList.
Списки это последовательность текстовых блоков, которые отформатированы обычным способом, но они также предоставляют стандартные отделки списка, такие как точки и перечисляемые элементы. Списки могут быть вложены, и у них будет отступ, если формат списка указывает ненулевой отступ.
Мы можем ссылаться на каждый элемент списка по его индексу в списки:
for (int index = 0; index < list->count(); ++index) { QTextBlock listItem = list->item(index); processListItem(listItem); }
Так как QTextList это подкласс QTextBlockGroup, он не группирует элементы списка в качестве дочерних элементов, но вместо этого предоставляет различные функции для управления ими. Это значит что любой текстовый блок, который мы найдем при перемещении по документу, может быть элементом списка. Мы можем убедиться, что элементы списка правильно идентифицируются, используя следующий код:
QTextFrame::iterator it; for (it = frame->begin(); !(it.atEnd()); ++it) { QTextBlock block = it.currentBlock(); if (block.isValid()) { QTextList *list = block.textList(); if (list) { int index = list->itemNumber(block); processListItem(list, index); } } }
Изображения в QTextDocument представлены текстовыми фрагментами, которые ссылаются на внешние изображения через механизм ресурсов. Изображения создаются с помощью интерфейса курсора и могут быть модифицированы позже, изменением символьного формата фрагмента изображения:
if (fragment.isValid()) { QTextImageFormat newImageFormat = fragment.charFormat().toImageFormat(); if (newImageFormat.isValid()) { newImageFormat.setName(":/images/newimage.png"); QTextCursor helper = cursor; helper.setPosition(fragment.position()); helper.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor); helper.setCharFormat(newImageFormat); } }
Фрагмент, который представляет изображение, может быть найден перебором фрагментов в текстовом блоке, которые содержат изображение.
[Предыдущая: Обработка форматированного текста] [Содержание] [Следующая: Интерфейс QTextCursor]
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Торговые марки | Qt 4.5.3 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |