Scribe框架提供一系列读和控制富文本文档的类。Qt4提供像QTextDocument类,他能够为开发提供创建和修改结构的富文本文档。
文档内的信息通过两个补充的接口存取:
1. 基于光标的接口用来编辑。2. 可读的分层接口它提供文档结构的高层次预览。使用前者的优点是他可以使用操纵符编辑,提供了一个很好的用户交互接口,不会损失潜在的文档结构。而后者的接口在查询和文档展示时最有用。
帮助文档分为了六个章节来介绍Rich Text Processing,可以仔细查阅:
Rich Text Document Structure
The QTextCursor Interface
Document Layouts
Common Rich Text Editing Tasks
Advanced Rich Text Processing
Supported HTML Subset
Rich Text Document Structure
QTextDocument类是文本文档的代表,它包含了构建富文本文档所需的信息。文档的结构是由分层的文本块(text blocks),frames,tables和一些其他的内容对象组成。新元素的创建和插入可以使用QTextCursor或者editor widget(例如QTextEdit)。如下图表示了他们的分层结构:
使用QTextEdit使展示编辑富文本非常容易,文档可以为任何编辑部件无关地创建,例如:
QTextDocument *newDocument = new QTextDocument;
也可以为已存在的编辑部件创建:
QTextEdit *editor = new QTextEdit;
QTextDocument *editorDocument = editor->document();
一个空文档包含一个root frame,这个root frame自己是包含一个空text block的。Frame不仅有分隔文档的功能,也有提供如何显示的功能。下面是获得root frame的方法:
QTextDocument *textDocument;
QTextFrame *root = textDocument->rootFrame();
Table是frame的专门类型,由一些单位(cells)组成,它们被安排成行和列,每一个都包含结构和文本。Table提供管理和呈现的特征,这样可以灵活的创建单位。Text blocks包含特殊化的文本和字符格式信息,例如字符的颜色,对齐,背景等等。以上的元素对应的类是QTextFrame, QTextTable, QTextBlock, (还有一个对应列表的类QTextList)。图片元素由特殊的text block代表。一组元素可以一起子类化为QTextBlockGroup,QTextBlockGroup是QTextFrame子类。
Text blocks可以通过QTextBlock::iterator遍历块的内部结构:
QTextBlock::iterator it;
for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
QTextFragment currentFragment = it.fragment();
if (currentFragment.isValid())
processFragment(currentFragment);
}
QTextBlock提供了比较操纵符:== != <用来判断两个块是否相同,出现的先后。
Text frames可以由一组块和子frames组成。所有的frame除了root frame,都有父frame。使用QTextFrame::iterator遍历frame的子元素:
QDomElement frameElement = ...
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);
}
QTextTable是QTextFrame的子类,所以tables可以像对待QTextFrame一样对待。它每一个单位(cell)的检查可以通过行列号:
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是QTextBlockGroup的子类,它可以使用索引获得QTextList对象的项。
for (int index = 0; index < list->count(); ++index) {
QTextBlock listItem = list->item(index);
processListItem(listItem);
}
Images在QTextDocument中由text fragment代表,由光标(cursor)接口创建,可以被字符格式修改:
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);
}
}
The QTextCursor Interface
文档可以通过QTextCursor提供的接口编辑,
使用cursor主要是用来插入或修改块中的文本,我们可以在编辑器中使用:
QTextEdit *editor = new QTextEdit();
QTextCursor cursor(editor->textCursor());
也可以直接从一个文档中获取。
QTextDocument *document = new QTextDocument(editor);
QTextCursor cursor(document);
一系列的编辑操作可以打包到一起去,这样可以使用beginEditBlock(),endEditBlock()实现,下面代码示例:
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
cursor.endEditBlock();
QTextCursor提供一些插入文档元素的操作:
insertBlock()
insertFrament()
insertImage()
insertText()
以上都不会返回插入元素,下面的操作会返回插入的元素:
insertFrame()
insertList()
insertTable()
一下是一些示例:
// insert Text
cursor.insertText(tr("Character formats"),
headingFormat);
cursor.insertBlock();
cursor.insertText(tr("Text can be displayed in a variety of " "different character formats. "), plainFormat); // 以某格式插入文本
cursor.insertText(tr("We can emphasize text by "));
cursor.insertText(tr("making it italic"), emphasisFormat);
// insert block
QTextBlockFormat backgroundFormat = blockFormat;
backgroundFormat.setBackground(QColor("lightGray"));
cursor.setBlockFormat(backgroundFormat);
// insert frame
QTextFrame *mainFrame = cursor.currentFrame();
cursor.insertText(...);
// 为子frame建立一个frame格式
QTextFrameFormat frameFormat;
frameFormat.setMargin(32);
frameFormat.setPadding(8);
frameFormat.setBorder(4);
QTextFrameFormat的格式示意图:
cursor.insertFrame(frameFormat);
cursor.insertText(...);
插入table:
QTextCursor cursor(editor->textCursor());
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
它也可以定义格式:
QTextTableFormat tableFormat;
tableFormat.setBackground(QColor("#e0e0e0"));
QVector<QTextLength> constraints;
constraints << QTextLength(QTextLength::PercentageLength, 16);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
constraints << QTextLength(QTextLength::PercentageLength, 28);
tableFormat.setColumnWidthConstraints(constraints);
QTextTable *table = cursor.insertTable(rows, columns, tableFormat);
插入list:
QTextListFormat listFormat;
if (list) {
listFormat = list->format();
listFormat.setIndent(listFormat.indent() + 1);
}
listFormat.setStyle(QTextListFormat::ListDisc);
cursor.insertList(listFormat);
插入images:
QTextImageFormat imageFormat;
imageFormat.setName(":/images/advert.png");
cursor.insertImage(imageFormat);:
Document Layouts
每个文档的布局都是子类化的QAbstractTextDocumentLayout类。QTextLayout可以帮助开发者呈现渲染文本,它可以用在plain和rich text。QTextLine是