QSortFilterProxyModel
фильтрует только столбцы или строки, не фильтрует элементы, поэтому стратегия для этого случая - преобразовать таблицу в список, а затем отфильтровать список, поскольку фильтрация строки эквивалентна фильтрации элемента и, наконец, преобразованиюсписок в таблицу.
import random
import math
from PyQt4 import QtCore, QtGui
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data, columns, parent=None):
super(TableModel, self).__init__(parent)
self._columns = columns
self._data = data[:]
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid() or self._columns == 0:
return 0
return math.ceil(len(self._data )*1.0/self._columns)
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._columns
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return
if role == QtCore.Qt.DisplayRole:
try:
value = self._data[ index.row() * self._columns + index.column() ]
return value
except:
pass
class Table2ListProxyModel(QtGui.QIdentityProxyModel):
def columnCount(self, parent=QtCore.QModelIndex()):
return 1
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self.sourceModel().rowCount() * self.sourceModel().columnCount()
def mapFromSource(self, sourceIndex):
if sourceIndex.isValid() and sourceIndex.column() == 0 \
and sourceIndex.row() < self.rowCount():
r = sourceIndex.row()
c = sourceIndex.column()
row = c * sourceIndex.model().columnCount() + r
return self.index(row, 0)
return QtCore.QModelIndex()
def mapToSource(self, proxyIndex):
r = proxyIndex.row() / self.sourceModel().columnCount()
c = proxyIndex.row() % self.sourceModel().columnCount()
return self.sourceModel().index(r, c)
def index(self, row, column, parent=QtCore.QModelIndex()):
return self.createIndex(row, column)
class ListFilterProxyModel(QtGui.QSortFilterProxyModel):
def setThreshold(self, value):
setattr(self, "threshold", value)
self.invalidateFilter()
def filterAcceptsRow(self, row, parent):
if hasattr(self, "threshold"):
ix = self.sourceModel().index(row, 0)
val = ix.data()
if val is None:
return False
return val < getattr(self, "threshold")
return True
class List2TableProxyModel(QtGui.QIdentityProxyModel):
def __init__(self, columns=1, parent=None):
super(List2TableProxyModel, self).__init__(parent)
self._columns = columns
def columnCount(self, parent=QtCore.QModelIndex()):
return self._columns
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return math.ceil(self.sourceModel().rowCount()/self._columns)
def index(self, row, column, parent=QtCore.QModelIndex()):
return self.createIndex(row, column)
def data(self, index, role=QtCore.Qt.DisplayRole):
r = index.row()
c = index.column()
row = r * self.columnCount() + c
if row < self.sourceModel().rowCount():
return super(List2TableProxyModel, self).data(index, role)
def mapFromSource(self, sourceIndex):
r = math.ceil(sourceIndex.row() / self.columnCount())
c = sourceIndex.row() % self.columnCount()
return self.index(r, c)
def mapToSource(self, proxyIndex):
if proxyIndex.isValid():
r = proxyIndex.row()
c = proxyIndex.column()
row = r * self.columnCount() + c
return self.sourceModel().index(row, 0)
return QtCore.QModelIndex()
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
data = [random.choice(range(10)) for i in range(20)]
l = QtGui.QHBoxLayout(self)
splitter = QtGui.QSplitter()
l.addWidget(splitter)
tv = QtGui.QTableView()
lv = QtGui.QListView()
lvf = QtGui.QListView()
tvf = QtGui.QTableView()
model = TableModel(data, 3, self)
proxy1 = Table2ListProxyModel(self)
proxy1.setSourceModel(model)
proxy2 = ListFilterProxyModel(self)
proxy2.setSourceModel(proxy1)
proxy2.setThreshold(5)
proxy3 = List2TableProxyModel(3, self)
proxy3.setSourceModel(proxy2)
tv.setModel(model)
lv.setModel(proxy1)
lvf.setModel(proxy2)
tvf.setModel(proxy3)
splitter.addWidget(tv)
splitter.addWidget(lv)
splitter.addWidget(lvf)
splitter.addWidget(tvf)
if __name__=="__main__":
import sys
a=QtGui.QApplication(sys.argv)
w=Widget()
w.show()
sys.exit(a.exec_())