Qt 富文本处理(02):富文本文档结构[官档翻译,迭代器是个参考]

前言

官方文档 Rich Text Processing - Rich Text Document Structure

  文本文档由QTextDocument 类表示,该类包含有关文档的内部表示、其结构的信息,并跟踪修改以提供撤消/重做功能。 
  文本文档的结构化表示形式将其内容呈现为文本块框架表格其他对象的层次结构。它们为文档提供了逻辑结构,并描述了其内容的显示方式。通常,框架和表格用于对其他结构进行分组,而文本块则包含实际的文本信息。
  
使用QTextCursor或使用编辑器小部件(如 QTextEdit)以编程方式创建和插入到文档中的新元素。元素在创建时可以指定特定格式;否则,它们会采用该元素的游标当前格式。

img基本结构 :  文档的层次如图所示。
 每个文档始终包含一个根框架,并且始终包含至少一个文本块。
 根框架通常包含一系列块和其他元素。
 框架和表的顺序始终由文档中的文本块分隔,即使文本块不包含任何信息。

  导航文档结构时,从根框架开始非常有用,因为它提供了对整个文档结构的访问。

富文本文档中的结构元素

  富文本文档通常由常见元素组成,如段落框架表格列表。这些由QTextBlock、QTextFrame、QTextTable和 QTextList类在QTextDocument中表示。 与文档中的其他元素不同,图像由特殊格式的文本片段表示。这样,它们可以与周围的文本保持格式。
  文档中的基本结构构建基本块是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提供了便于操作块的比较运算符:运算符= 、!= 用于测试两个块是否相同,运算符 < 用于确定文档中哪个块先出现。

框架

  帧由QTextFrame 类提供。
  文本框架将文本块和子框架分组在一起,创建大于段落的文档结构。框架的格式指定如何在页面上呈现和定位框架。框架要么插入到文本流中,要么浮动在页面的左侧或右侧。每个文档都包含一个包含所有其他文档元素的根框架。因此,除根帧外,所有帧都有父帧。
  由于文本块用于分隔其他文档元素,因此每个框架将始终包含至少一个文本块和零个或多个子框架。我们可以使用 QTextFrame::iterator 来遍历帧的子元素来检查帧的内容:

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);
}

注意,迭代器会同时选择帧和块,因此有必要检查它所指的是哪个。 这使我们可以逐帧浏览文档结构,但仍可以根据需要访问文本块。 QTextBlock :: iterator和QTextFrame :: iterator类都可以互补使用,以从文档中提取所需的结构。

  表由QTextTable 类提供。

  表是按行和列排列的单元格集合。每个表单元格都是具有其自身字符格式的文档元素,但它也可以包含其他元素,如框架和文本块。在构造表或添加额外的行或列时,将自动创建表单元格。它们也可以在表之间移动。

  QTextTable是QTextFrame 的子类,因此表在文档结构中被视为框架。对于我们在文档中遇到的每个帧,我们可以测试它是否表示表,并使用不同的方式处理它:

QDomElement frameElement = ...

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);
     }
 }

  通过遍按包含图像的文本块中的片段,可以找到表示图像的片段。

总结

  富文本文档通常由常见元素组成,如段落框架表格列表。分别对应于QTextBlock、QTextFrame、QTextTable和 QTextList类在QTextDocument中表示。 与文档中的其他元素不同,图像由特殊格式的文本片段表示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值