我正在使用QSortFilterProxyModel来过滤来自QAbstractListModel的结果。但是,我想返回第一个条目,该条目在原始模型中不存在,也就是说,它某种程度上是人为的。
这是我到目前为止的内容:
class ActivedAccountModel(QSortFilterProxyModel):
def __init__(self, model, parent=None):
super(ActiveAccountModel, self).__init__(parent)
self.setSourceModel(model)
self.setDynamicSortFilter(True)
def data(self, index, role=Qt.DisplayRole):
account_info = super(ActiveAccountModel, self).data(index, Qt.UserRole).toPyObject()
if role == Qt.DisplayRole:
return account_info.name
elif role == Qt.UserRole:
return account_info
return None
def filterAcceptsRow(self, source_row, source_parent):
source_model = self.sourceModel()
source_index = source_model.index(source_row, 0, source_parent)
account_info = source_model.data(source_index, Qt.UserRole)
return isinstance(account_info.account, Account) and account_info.account.enabled
Run Code Online (Sandbox Code Playgroud)
这将以以下形式返回列表:
Account 1
Account 2
...
Run Code Online (Sandbox Code Playgroud)
我想在返回的列表f元素的开头返回一个额外的元素:
Extra Element
Account 1
Account 2
...
Run Code Online (Sandbox Code Playgroud)
我试图重新实现rowCount以便返回真实的rowCount()+ 1,但是以某种方式我需要移动所有项才能返回索引0处的该人造元素,而我在那里有点迷失了。
有什么线索吗?到目前为止,我找不到任何相关的代码示例...谢谢!
小智 5
因为我在实现这个过程中遇到了一些困难,并且因为我在整个网络中找不到任何其他示例代码,所以我发布了这个示例实现。
我希望这也对其他人有帮助......
/**
** Written by Sven Anders (ANDURAS AG). Public domain code.
**/
#include <QDebug>
#include <QBrush>
#include <QFont>
#include <QSortFilterProxyModel>
/** Definition **/
class ProxyModelNoneEntry : public QSortFilterProxyModel
{
Q_OBJECT
public:
ProxyModelNoneEntry(QString _entry_text = tr("(None)"), QObject *parent=0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
/* lessThan() is not necessary for this model to work, but can be
implemented in a derived class if a custom sorting method is required. */
// bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
private:
QString entry_text;
};
/** Implementation **/
ProxyModelNoneEntry::ProxyModelNoneEntry(QString _entry_text, QObject *parent) : QSortFilterProxyModel(parent)
{
entry_text = _entry_text;
}
int ProxyModelNoneEntry::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return QSortFilterProxyModel::rowCount()+1;
}
QModelIndex ProxyModelNoneEntry::mapFromSource(const QModelIndex &sourceIndex) const
{
if (!sourceIndex.isValid()) return QModelIndex();
else if (sourceIndex.parent().isValid()) return QModelIndex();
return createIndex(sourceIndex.row()+1, sourceIndex.column());
}
QModelIndex ProxyModelNoneEntry::mapToSource(const QModelIndex &proxyIndex) const
{
if (!proxyIndex.isValid()) return QModelIndex();
else if (proxyIndex.row() == 0) return QModelIndex();
return sourceModel()->index(proxyIndex.row()-1, proxyIndex.column());
}
QVariant ProxyModelNoneEntry::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return QVariant();
if (index.row() == 0)
{
if (role == Qt::DisplayRole)
return entry_text;
else if (role == Qt::DecorationRole)
return QVariant();
else if (role == Qt::FontRole)
{ QFont font; font.setItalic(true); return font; }
else
return QVariant();
}
return QSortFilterProxyModel::data(createIndex(index.row(),index.column()), role);
}
Qt::ItemFlags ProxyModelNoneEntry::flags(const QModelIndex &index) const
{
if (!index.isValid()) return Qt::NoItemFlags;
if (index.row() == 0) return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
return QSortFilterProxyModel::flags(createIndex(index.row(),index.column()));
}
QModelIndex ProxyModelNoneEntry::index(int row, int column, const QModelIndex &parent) const
{
if (row > rowCount()) return QModelIndex();
return createIndex(row, column);
}
QModelIndex ProxyModelNoneEntry::parent(const QModelIndex &child) const
{
Q_UNUSED(child)
return QModelIndex();
}
Run Code Online (Sandbox Code Playgroud)
问候斯文
我只在工作中这样做过,所以我不能给你太多代码。我可以为您提供该做什么的总体思路。
如果您继承QAbstractProxyModel ,效果会更好,它是为一般操作而设计的,而不是排序或过滤。您需要覆盖 rowCount,并且还需要覆盖 columnCount(尽管这应该只返回来自源模型的信息)。您需要重写数据函数并返回您自己的第一行数据,或者再次调用源模型。
您将需要重写 mapFromSource 和 mapToSource 函数,以允许在代理模型索引和源模型索引之间切换。
为了实现稳健的实现,您需要创建一些槽并连接到源模型的信号,以进行数据更改、模型重置以及要插入/删除的行/列。然后,您应该发出自己的信号,并适当地调整它们以考虑您的额外行。
在我们的课程中,我们使第一行的文本可设置,因此我们可以在不同的情况下使用相同的代理模型。这值得您进行研究,因为它只增加了最少的工作量。
编辑
根据评论请求,粗略地了解一下mapToSource 和mapFromSource。这大约是您需要考虑的问题。
// Remember that this maps from the proxy's index to the source's index,
// which is invalid for the extra row the proxy adds.
mapToSource( proxy_index ):
if proxy_index isn't valid:
return invalid QModelIndex
else if proxy_index is for the first row:
return invalid QModelIndex
else
return source model index for (proxy_index.row - 1, proxy_index.column)
mapFromSource( source_index ):
if source_index isn't valid:
return invalid QModelIndex
else if source_index has a parent:
// This would occur if you are adding an extra top-level
// row onto a tree model.
// You would need to decide how to handle that condition
return invalid QModelIndex
else
return proxy model index for (source_index.row + 1, source_index.column)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2600 次 |
| 最近记录: |