[译]QSortFilterProxyModel文档
Detailed Description
QSortFilterProxyModel 供给了支撑了在其他模型(model)和视图(view)之间传递数据时停止排序(sorting)和过滤(filtering)。
QSortFilterProxyModel 可以用于排序(sorting) items或者过滤(filtering out)items或者排序并且过滤items。它把一个model的source结构通过model的index结构map到他新供给的index里面,这种方法允许一个model重新组织,当和他相关联的view,不须要在数据上请求任何转换,也不须要复制内存中的数据。
假设我们想要在一个自定义model(custom model)供给排序(sort)和过滤(filter )items。在没有供给排序(sorting)和过滤的(filtering)功能的情况下,建立模型(model)和视图(view)的代码类似如下:
QTreeView *treeView = new QTreeView;
MyItemModel *model = new MyItemModel(this);
treeView->setModel(model)
为了对 MyItemModel 添加排序(sorting)和过滤(filtering)的支撑,我们须要创建一个QSortFilterProxyModel(对象),调用setSourceModel()函数并将 MyItemModel (对象),作为函数的参数,然后在视图(view)上安装(install) QSortFilterProxyModel(对象),:
QTreeView *treeView = new QTreeView; MyItemModel *sourceModel = new MyItemModel(this); QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(sourceModel); treeView->setModel(proxyModel);
当初,无论是排序(sorting )还是过滤(filtering)都还未启用,原始数据表当初视图(view)上。通过QSortFilterProxyModel做的任何修改都会作用在原始模型(model)中。
QSortFilterProxyModel对于原始的模型(model)来讲就相当于一个包装工具。如果想把原始的QModelIndex转换成可排序(sorted)/过滤(filtered)的模型(model),或者反之亦然,使用 mapToSource(), mapFromSource(), mapSelectionToSource(), 和mapSelectionFromSource()这些方法。
注意:默许情况下,不管原始的模型(origina model)何时改变,它会动态自动重新排序(re-sorts )和重新过滤(re-filters )数据。
Basic Sort/Filter Model 和 Custom Sort/Filter Model 例子说明了如何使用QSortFilterProxyModel来执行基本的排序(sorting)和过滤filtering ()和如何实现自定义子类(subclass)行为。
Sorting
QTableView and QTreeView have a sortingEnabled property that controls whether the user can sort the view by clicking the view's horizontal header. For example:
QTableView 和 QTreeView 有一个sortingEnabled属性,控制着用户是不是可以通过点击视图(view)的水平标题栏(horizontal header)来排序。例如:
treeView->setSortingEnabled(true);
当这个性质(feature)打开时(默许是关闭(off)),点击表头(header section)就会对本列(columm)的item停止排序(sorts).通过重复点击表头(header),用户可以交替的看到升序(ascending)和降序(descending order)的排序。
在幕后(Behind the scene),视图(view)调用模型(model)中的虚函数sort()重新排序(reorder)模型(model)中的数据。为了是自己的数据可以排序(sortable),我们可以在自己的模型(model)实现sort()方法,或者使用QSortFilterProxyModel来包装(wrap)这个模型(model)——QSortFilterProxyModel 供给了一个通用sort()的重新实现,来操纵items的sortRole() (默许是Qt::DisplayRole)。QSortFilterProxyModel 的sort()函数可以操纵多种数据类型,包含:int、 QString 和QDateTime. 对于分层模型(hierarchical models),排序(sorting)是递归(recursively)地应用到所有子元素(child items)。在默许情况下,字符串比较是大小写敏感的(case sensitive);这个属性可以通过设置 sortCaseSensitivity 来改变。
自定义排序的行为时通过子类化(subclassing) QSortFilterProxyModel 和重新实现 lessThan() 方法。lessThan()是用来比较items的大小。例如:
1 bool MySortFilterProxyModel::lessThan(const QModelIndex &left, 2 const QModelIndex &right) const 3 { 4 QVariant leftData = sourceModel()->data(left); 5 QVariant rightData = sourceModel()->data(right); 6 7 if (leftData.type() == QVariant::DateTime) { 8 return leftData.toDateTime() < rightData.toDateTime(); 9 } else { 10 QRegExp *emailPattern = new QRegExp("([\\w\\.]*@[\\w\\.]*)"); 11 12 QString leftString = leftData.toString(); 13 if(left.column() == 1 && emailPattern->indexIn(leftString) != -1) 14 leftString = emailPattern->cap(1); 15 16 QString rightString = rightData.toString(); 17 if(right.column() == 1 && emailPattern->indexIn(rightString) != -1) 18 rightString = emailPattern->cap(1); 19 20 return QString::localeAwareCompare(leftString, rightString) < 0; 21 } 22 }
(这个代码片段来自Custom Sort/Filter Model的例子)
另一种排序(sorting)是禁用对视图(view)停止排序(sorting ),并强加给用户以特定的次序。这是在 QSortFilterProxyModel 通过显式调用(explicitly calling ) sort () 用所需的列(desired column )和次序作为参数 (或上的原始模型(original model )实现 sort())。例如:
proxyModel->sort(2, Qt::AscendingOrder);
QSortFilterProxyModel 可以按-1列(column -1)排序(sorted),在这种情况下它返回到底层的源模型的排序次序(the sort order of the underlying source model)。
Filtering
除了排序(sorting),QSortFilterProxyModel 可以用于隐藏与特定过滤器(a certain filter)不匹配的items。对于给定的一列,指定的过滤器(filter)使用QRegExp对象并应用于filterRole()(默许情况下是Qt::DisplayRole)的每一个items。QRegExp 对象可以用于匹配正则表达式、 通配符模式或一个固定的字符串。例如:
proxyModel->setFilterRegExp(QRegExp(".png", Qt::CaseInsensitive,
QRegExp::FixedString));
proxyModel->setFilterKeyColumn(1);
对于分层模型(hierarchical models),过滤器(filter)被递归地应用到所有的孩子(children).如果一个父项(parent item)不匹配过滤器,它的所有孩子(children)将被表现。
平日的一个用法是让用户通过QLineEdit指定过滤器(filte)正则表达式,通配符,然后通过连接textChanged()信号到槽setFilterRegExp(), setFilterWildcard(), setFilterFixedString()来响应过滤器(filter)。
自定义过滤(Custom filtering)行为可以通过重新实现 filterAcceptsRow() 和 filterAcceptsColumn() 函数。例如 (实例:Custom Sort/Filter Model),下面的实现将疏忽 filterKeyColumn 属性和执行过滤(performs filtering )列 0、 1 和 2 :
1 bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, 2 const QModelIndex &sourceParent) const 3 { 4 QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent); 5 QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent); 6 QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent); 7 8 return (sourceModel()->data(index0).toString().contains(filterRegExp()) 9 || sourceModel()->data(index1).toString().contains(filterRegExp())) 10 && dateInRange(sourceModel()->data(index2).toDate()); 11 }
(这个代码片段来自Custom Sort/Filter Model的例子)
如果正在使用大批的筛选,并有多次调用 invalidateFilter(),使用reset()可能更有效,具体取决于模型(model)的实现。但是,reset()返回代理模型(proxy model )其最初的状态(original state)。这个状态失去了选择的信息(selection information),并将致使代理服模型(proxy model )必须重新填充(repopulated)。
Subclassing
因为 QAbstractProxyModel 和它的子类从 QAbstractItemModel 派生的很多关于创建子类畸形模式的雷同建议也适用于代理模式。此外,值得注意很多此类中的函数的默许实现,以便他们有关源模型中调用等效的功能( In addition, it is worth noting that many of the default implementations of functions in this class are written so that they call the equivalent functions in the relevant source model. )。这种简略的代理机制可能须要覆盖源模型(source models )实现更复杂的行为;例如,如果源模型(source model )供给了一个自定义(custom)的hasChildren() 实现,则应还供给一个代理模型(代理模型)中。
查看原文:http://wavelee.info/2013/05/26/qsortfilterproxymodel-class/
官方文档:http://qt-project.org/doc/qt-4.8/qsortfilterproxymodel.html

浙公网安备 33010602011771号