PDA

View Full Version : Filter columns in QAbstractItemModel



Djab
30th July 2012, 14:42
Hi all readers,

I've got a Model (a sub class of QAbstractTableModel) that work like a charm what ever the standard view I plug it in, that do not support the sort function.

But this model as 'too' many columns most of the time... (thinks of it as the result of select * from table).

So I build a simple model that filter columns, here is the code (in python) (btw I wanted to use QIdentityProxyModel but it does not exist in Qt 4.7...):


class ModelColumnFilter(QtGui.QSortFilterProxyModel):
def __init__(self):
QtGui.QSortFilterProxyModel.__init__(self)
self.colMapFromSource = {} # col source -> col proxy
self.colMapFromProxy = tuple() # col proxy -> col source

def set_column_to_display(self, column_to_display):
self.beginResetModel()
self.colMapFromProxy = tuple(column_to_display)
for i, x in enumerate(self.colMapFromProxy):
self.colMapFromSource[x] = i
self.endResetModel()

def flags(self, index):
return self.sourceModel().flags(self.mapToSource(index))

def setSourceModel(self, sourceModel):
QtGui.QSortFilterProxyModel.setSourceModel(self, sourceModel)
# by default display all column with same order
self.set_column_to_display(
tuple(i for i in xrange(self.sourceModel().columnCount())))

def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.colMapFromProxy)

def mapFromSource(self, sourceIndex):
if sourceIndex.isValid():
if sourceIndex.column() in self.colMapFromSource:
return self.createIndex(sourceIndex.row(),
self.colMapFromSource[sourceIndex.column()])
return QtCore.QModelIndex()

def mapToSource(self, proxyIndex):
if proxyIndex.isValid():
return self.sourceModel().index(proxyIndex.row(),
self.colMapFromProxy[proxyIndex.column()])
return QtCore.QModelIndex()


So, whatever the number of view I'm using to display data in this model, they see only what I need (more over in the order I need).

This work great if I use it as is.

But if I want to sort columns, and use an other QSortFilterProxyModel like this:

mo = MyModel()

mf = ModelColumnFilter()
mf.setSourceModel(mo)
set_column_to_display([....])

mp = QtGui.QSortFilterProxyModel()
mp.setSourceModel(mf)

view1 = QtGui.QTreeView()
view1.setModel(mp)
view1.setSortingEnabled(True)


view2 = QtGui.QTreeView()
view2.setModel(mp)
view2.setSortingEnabled(True)


view2 cause the application to crash.
I suppose it's a problem in my model (an index not very well formed ??).

Tell me if I'm doing it wrong, or How can I change this to make it work.

Thanks

StrikeByte
31st July 2012, 15:39
Hi,

I think the problem is that you try to connect two views to only one QSortFilterProxyModel you can try to create two sepatate QSortFilterProxyModel's for each view one

ecanela
3rd August 2012, 07:28
QSortFilterProxyModel only filter rows, if you need filter columns the easy way is rewrite the DB query to include ONLY the column you need.

BTW: QIdentityProxyModel cant sort or filter the data in the model. QIdentityProxyModel is more suitable for transform the data of the source model. transforms like change num of second in a format "mm:ss" convert all the string to upper.

ecanela
3rd August 2012, 17:32
another option is hide the columns in the view. but still is preferable rewrite your querys.