QSortFilterProxyModel返回人工行

sag*_*hul 5 python qt pyqt

我正在使用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)

问候斯文


Cal*_*itt 2

我只在工作中这样做过,所以我不能给你太多代码。我可以为您提供该做什么的总体思路。

如果您继承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)