I'm using a QSortFilterProxyModel to filter results from a QAbstractListModel. However, I'd like to return a first entry which is not present in the original model, that is, it's somehow artificial.
This is what I have so far:
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.nameelif role == Qt.UserRole:return account_inforeturn Nonedef 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
This will return a list in the form of:
Account 1
Account 2
...
Id' like to return an extra element at the begining of the returned list f elements:
Extra Element
Account 1
Account 2
...
I tried to reimplement rowCount in order to return the real rowCount()+1, but somehow I'd need to shift all the items in order to return this artificial element at index 0, and I'm a bit lost there.
Any clue? I couldn't find any related code example so far... Thanks!
Because I struggled a little bit with the implementation of this and because I could not find any other sample code in the whole net, I post this sample implementation.
I hope this helps other people too...
/**** Written by Sven Anders (ANDURAS AG). Public domain code.**/#include <QDebug>
#include <QBrush>
#include <QFont>
#include <QSortFilterProxyModel>/** Definition **/class ProxyModelNoneEntry : public QSortFilterProxyModel
{Q_OBJECTpublic: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 beimplemented 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; }elsereturn 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();
}
RegardsSven