PDA

View Full Version : PyQt5 QSortFilterProxyModel: index from wrong model passed to mapFromSource + segfalt



lcarlier
20th February 2018, 19:05
Hi,

I'm having issue with what I believe to be an hello world example.

I'm trying to implement a QSortFilterProxyModel to filter a Table which takes its data from a subclass of QAbstractTableModel.

The problem that I have is that whenever I'm selecting a cell and then start filtering, I'm having a segmentation fault from the python interpreter. The stacktrace guides me to mapFromSource in a QT shared object. Sometime I see the following error in the terminal in which I'm running my QtApplication

index from wrong model passed to mapFromSource

I've checked the Qt Documentation and I'm following the recommendation when subclassing QAbstractTableModel and QSortFilterProxyModel.

Here is my implementation of my QAbstractTableModel and QSortFilterProxyModel


class MyTableModel(QAbstractTableModel):
def __init__(self, datain, parent=None, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.arraydata = datain

def rowCount(self, parent):
return len(self.arraydata)

def columnCount(self, parent):
return BankRecord.getMaxIdx()

def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()].getIdxData(index.column()))

def headerData(self, section, orientation, role):
if orientation == QtCore.Qt.Vertical:
return QVariant()
if role != Qt.DisplayRole:
return QVariant()
return QVariant(BankRecord.getIdxHeaderData(section))

class RecordFilter(QSortFilterProxyModel):
def __init__(self, parent):
super(RecordFilter,self).__init__(parent)
self.filterHeader = None

def setFilterHeader(self, filterHeader):
self.filterHeader = filterHeader

def filterAcceptsRow(self, source_row, source_parent):
sourceModel = self.sourceModel()
if not self.filterHeader:
return False
for i in range(BankRecord.getMaxIdx()):
idx = sourceModel.index(source_row, i, source_parent)
dataString = sourceModel.data(idx, Qt.DisplayRole).value().lower()
filterText = self.filterHeader.filterText(i).lower()
if len(filterText) > 0 and not dataString.find(filterText) >= 0:
return False
return True

If you are curious, the rest of the source code of my application is available on Github (https://github.com/lcarlier/BankRecordsAnalyzer)
You can easily test the problem because there is a record directly inserted into the table. Then you must play a bit with the filter (adding removing characters in filter fields) and the application is eventually crashing.

Has anybody an idea what my problem is?

Kind regards,

Laurent

lcarlier
18th March 2018, 20:16
Hi,
I received a personal mail from a person who gave me the answer.
I'm posting it here so that it can help other person if needed.
The problem that I had is that whenever my filter was updated I was calling the method

tableModel.layoutChanged.emit()
iso of the method

proxy.invalidateFilter()
Thanks to Norman Brown for contacting me and giving me that answer.
Kind regards,
Laurent