[PyQt] Bug Report: pyqt5 discard silently signal with missing optional parameters (dataChanged roles for example)

Baptiste Lepilleur baptiste.lepilleur at gmail.com
Fri Jan 10 22:08:49 GMT 2014


The issue is demonstrated in the attached example (pyqt 5.2, python 3.3).
Below is the relevant excerpt:

class ListModel(QAbstractItemModel):
    def __init__(self, parent=None):
        super(ListModel, self).__init__(parent)

    def testEmit(self):
        # This signal is silently dropped by pyqt (missing optional 3rd
parameters). Why?
        self.dataChanged.emit(self.createIndex(1,0), QModelIndex())
        # This signal is sent as expected
        self.dataChanged.emit(self.createIndex(2,0), QModelIndex(), [])

* Bug description:

The signal QAbstractItemModel::dataChanged has the following signature:
void QAbstractItemModel::dataChanged(
    const QModelIndex & topLeft,
    const QModelIndex & bottomRight,
    const QVector<int> & roles = QVector<int> ())

If the optional roles parameters is not given when calling emit, the signal
emission is discarded without any error reporting.

For example:
        self.dataChanged.emit(self.createIndex(1,0), QModelIndex())

Below is the output of the attached example showing that the expected first
emit "onDataChanged 1" is missing:

C:\Python33\python.exe debugemit.py
onDataChanged 2
------------done-------------


* Work-around:

Pass the optional roles signal parameter:
        self.dataChanged.emit(self.createIndex(2,0), QModelIndex(), [])

* Remarks:

This bug usually goes unseen because the views are usually automatically
refreshed if the mouse if moved over the view associated to the model.

It was exposed by a model shared by multiple editable views with a custom
setData(). It took many hours to figure out the root cause of the lack of
refresh.

IMHO a fairly serious bug as I've never seen an example of
dataChanged.emit() with the roles parameter...

Let's me know if the above is unclear or more details are required, I'd
hate to see anyone else losing time on this issue,
Baptiste.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20140110/edaf49e6/attachment.html>
-------------- next part --------------
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class ListModel(QAbstractItemModel):
    def __init__(self, parent=None):
        super(ListModel, self).__init__(parent)

    def testEmit(self):
        # This signal is silently dropped by pyqt (missing optional 3rd parameters). Why?
        self.dataChanged.emit(self.createIndex(1,0), QModelIndex())
        # This signal is sent as expected
        self.dataChanged.emit(self.createIndex(2,0), QModelIndex(), [])

class MyDebugWidget(QWidget):
    def __init__(self):
        super(MyDebugWidget, self).__init__()

    def testConnect(self):
        self.model = ListModel()
        self.model.dataChanged.connect( self.onDataChanged )
        self.model.testEmit()
        print('------------done-------------')

    def onDataChanged(self, index1, index2, roles):
        print('onDataChanged', index1.row())


def main():
    app = QApplication(sys.argv)
    w = MyDebugWidget()
    w.testConnect()

if __name__ == "__main__":
    main()


More information about the PyQt mailing list