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是QTextLayout内的一排文本,可以QTextLayout::createLine()创建。
下面是个例子:
QTextLayout textLayout(text, font);
qreal margin = 10;
qreal radius = qMin(width()/2.0, height()/2.0) - margin;
QFontMetrics fm(font);
qreal lineHeight = fm.height();
qreal y = 0;
textLayout.beginLayout();
while (1) {
// create a new line
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
qreal x1 = qMax(0.0, pow(pow(radius,2)-pow(radius-y,2), 0.5));
qreal x2 = qMax(0.0, pow(pow(radius,2)-pow(radius-(y+lineHeight),2), 0.5));
qreal x = qMax(x1, x2) + margin;
qreal lineWidth = (width() - margin) - x;
line.setLineWidth(lineWidth);
line.setPosition(QPointF(x, margin+y));
y += line.height();
}
textLayout.endLayout();
QPainter painter;
painter.begin(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.fillRect(rect(), Qt::white);
painter.setBrush(QBrush(Qt::black));
painter.setPen(QPen(Qt::black));
textLayout.draw(&painter, QPoint(0,0));
painter.setBrush(QBrush(QColor("#a6ce39")));
painter.setPen(QPen(Qt::black));
painter.drawEllipse(QRectF(-radius, margin, 2*radius, 2*radius));
painter.end();
Common Rich Text Editing Tasks
我们通常用QTextBrowser和QTextEdit完成富文本编辑任务,通过QTextDocument创建文档,QTextCursor编辑,用文档结构展示。
例如利用文本编辑器部件展示HTML:
QTextEdit *editor = new QTextEdit(parent);
editor->setHtml(aStringContainingHTMLtext);
editor->show();
默认情况下,文本编辑器包含一个带有root frame的文档,可以editor->document()获得,可使用editor->textCursor()获得编辑器的光标QTextCursor。
选择文本,通过移动光标,例如:QTextCursor::MoveMode(MoveAnchor, KeepAnchor)
cursor.movePosition(QTextCursor::StartOfWord);
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
查找文本,下面是查找一个单词,并改变它的颜色以显示:
QTextCursor newCursor(document);
while (!newCursor.isNull() && !newCursor.atEnd()) {
newCursor = document->find(searchString, newCursor);
if (!newCursor.isNull()) {
newCursor.movePosition(QTextCursor::WordRight,
QTextCursor::KeepAnchor);
newCursor.mergeCharFormat(colorFormat);
}
}
打印文本,QTextEdit可以自动在一页大小的地方断开,以适应打印。QTextDocument提供print()函数允许打印。例如所示代码:
QTextDocument *document = editor->document();
QPrinter printer;
QPrintDialog *dlg = new QPrintDialog(&printer, this);
if (dlg->exec() != QDialog::Accepted)
return;
document->print(&printer);
Advanced Rich Text Processing
处理大文件
Qt 不限制文本处理的文件大小,对于大多数情况而言,这将不会出现问题。文件大小依赖于你硬件和你的Qt程序实现。
如果你面对了这个问题,我们推荐你
1. 你应该考虑断开大段成为更小的段落,你也可以定期插入换行符,这样就看起来像QTextEdit的一个大段。
2. 你可以在QTextDocument中用maximumBlockCount()减少块的数量,文档只和QTextEdit涉及到的块数量大小相当。
3. 当增加文本到一个文本编辑时,这是一个增加文本到编辑块(看下例)的优势。结果是文本编辑不是立刻需要全部文档结构的。
下面的例子我们假设文本编辑是可见的。
textEdit.show();
textCursor.beginEditBlock();
for (int i = 0; i < 1000; ++i) {
textCursor.insertBlock();
textCursor.insertText(paragraphText.at(i));
}
textCursor.endEditBlock();
Supported HTML Subset
Widgets使用QTextDocument能够展示特殊的富文本,例如QLabel, QTextEdit。
在Text Widget使用HTML标记
Widget会在展示时自动删除HTML标记,并根据含义展示富文本。例如,设置一个文本标签:"<b>Hello</b> <i>Qt!</i>",它会展示出这样:Hello Qt!
所支持的标记有:
Tag | Description | Comment |
a | Anchor or link | Supports the href and name attributes. Note that the :visited selector is one of those that is not supported by the rich text engine. See below for a list of others. |
address | Address | |
b | Bold | |
big | Larger font | |
blockquote | Indented paragraph | |
body | Document body | Supports the bgcolor attribute, which can be a Qt color name or a #RRGGBB color specification. |
br | Line break | |
center | Centered paragraph | |
cite | Inline citation | Same as i. |
code | Code | Same as tt. |
dd | Definition data | |
dfn | Definition | Same as i. |
div | Document division | Supports the standard block attributes. |
dl | Definition list | Supports the standard block attributes. |
dt | Definition term | Supports the standard block attributes. |
em | Emphasized | Same as i. |
font | Font size, family, and/or color | Supports the following attributes: size, face, and color (Qt color names or #RRGGBB). |
h1 | Level 1 heading | Supports the standard block attributes. |
h2 | Level 2 heading | Supports the standard block attributes. |
h3 | Level 3 heading | Supports the standard block attributes. |
h4 | Level 4 heading | Supports the standard block attributes. |
h5 | Level 5 heading | Supports the standard block attributes. |
h6 | Level 6 heading | Supports the standard block attributes. |
head | Document header | |
hr | Horizontal line | Supports the width attribute, which can be specified as an absolute or relative (%) value. |
html | HTML document | |
i | Italic | |
img | Image | Supports the src, source (for Qt 3 compatibility), width, and height attributes. |
kbd | User-entered text | |
meta | Meta-information | If a text encoding is specified using the meta tag, it is picked up by Qt::codecForHtml(). Likewise, if an encoding is specified toQTextDocument::toHtml(), the encoding is stored using a meta tag, for example: <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" /> |
li | List item | |
nobr | Non-breakable text | |
ol | Ordered list | Supports the standard list attributes. |
p | Paragraph | Left-aligned by default. Supports the standard block attributes. |
pre | Preformated text | |
qt | Qt rich-text document | Synonym for html. Provided for compatibility with earlier versions of Qt. |
s | Strikethrough | |
samp | Sample code | Same as tt. |
small | Small font | |
span | Grouped elements | |
strong | Strong | Same as b. |
style | Style sheet | Allows styling information to be included with the rich text. A limited subset of CSS syntax can be used to change the appearance of the text. |
sub | Subscript | |
sup | Superscript | |
table | Table | Supports the following attributes: border, bgcolor (Qt color names or #RRGGBB), cellspacing, cellpadding, width(absolute or relative), and height. |
tbody | Table body | Does nothing. |
td | Table data cell | Supports the standard table cell attributes. |
tfoot | Table footer | Does nothing. |
th | Table header cell | Supports the standard table cell attributes. |
thead | Table header | If the thead tag is specified, it is used when printing tables that span multiple pages. |
title | Document title | The value specified using the title tag is available through QTextDocument::metaInformation(). |
tr | Table row | Supports the bgcolor attribute, which can be a Qt color name or a #RRGGBB color specification. |
tt | Typewrite font | |
u | Underlined | |
ul | Unordered list | Supports the standard list attributes. |
var | Variable | Same as i. |
块block属性。这下面的属性被div, dl, dt, h1, h2, h3, h4, h5, h6, p支持:
align(left, right, center, justify)
dir(ltr, rtl)
列表list属性。下面的属性被ol, ul支持:
type (1, a, A, square, disc, circle)
表单位Table Cell属性。下面的被td, th标记支持:
width (absolute, relative, or no-value)
bgcolor (Qt color names or #RRGGBB )
colspan
rowspan
align (left, right, center, justify)
valign (top, middle, bottom)
CSS属性
Version:Property | Values | Description |
background-color | <color> | Background color for elements |
background-image | <uri> | Background image for elements |
color | <color> | Text foreground color |
font-family | <family name> | Font family name |
font-size | [ small | medium | large | x-large | xx-large ] | <size>pt | <size>px | Font size relative to the document font, or specified in points or pixels |
font-style | [ normal | italic | oblique ] | |
font-weight | [ normal | bold | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 ] | Specifies the font weight used for text, where normal and bold are mapped to the corresponding QFont weights. Numeric values are 8 times the equivalent QFont weight values. |
text-decoration | none | [ underline || overline || line-through ] | Additional text effects |
font | [ [ <'font-style'> || <'font-weight'> ]? <'font-size'> <'font-family'> ] | Font shorthand property |
text-indent | <length>px | First line text indentation in pixels |
white-space | normal | pre | nowrap | pre-wrap | Declares how whitespace in HTML is handled. |
margin-top | <length>px | Top paragraph margin in pixels |
margin-bottom | <length>px | Bottom paragraph margin in pixels |
margin-left | <length>px | Left paragraph margin in pixels |
margin-right | <length>px | Right paragraph margin in pixels |
padding-top | <length>px | Top table cell padding in pixels |
padding-bottom | <length>px | Bottom table cell padding in pixels |
padding-left | <length>px | Left table cell padding in pixels |
padding-right | <length>px | Right table cell padding in pixels |
padding | <length>px | Shorthand for setting all the padding properties at once. |
vertical-align | baseline | sub | super | middle | top | bottom | Vertical text alignment. For vertical alignment in text table cells only middle, top, and bottom apply. |
border-color | <color> | Border color for text tables. |
border-style | none | dotted | dashed | dot-dash | dot-dot-dash | solid | double | groove | ridge | inset | outset | Border style for text tables. |
background | [ <'background-color'> || <'background-image'> ] | Background shorthand property |
page-break-before | [ auto | always ] | Make it possible to enforce a page break before the paragraph/table |
page-break-after | [ auto | always ] | Make it possible to enforce a page break after the paragraph/table |
float | [ left | right | none ] | Specifies where an image or a text will be placed in another element. Note that the floatproperty is only supported for tables and images. |
text-transform | [ uppercase | lowercase ] | Select the transformation that will be performed on the text prior to displaying it. |
font-variant | small-caps | Perform the smallcaps transformation on the text prior to displaying it. |
word-spacing | <width>px | Specifies an alternate spacing between each word. |
支持CSS选择器,所有CSS2.1选择器都支持,除了pseudo-class选择器,例如:first-child, :visited 和 :hover