Missing QAbstractItemModel.multiData binding

Charles peacech at gmail.com
Tue Aug 29 14:17:45 BST 2023


Hi Phil, here is an example standalone code

import sys
from dataclasses import dataclass

from PyQt6.QtCore import QAbstractTableModel, Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView


@dataclass
class Item:
    name: str
    weight: int


class Model(QAbstractTableModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._items = [Item('A', 10), ('B', 11)]

    def rowCount(self, index):
        return len(self._items)

    def columnCount(self, index):
        return 2

    def _itemData(self, item, column):
        match column:
            case 0:
                return {Qt.ItemDataRole.DisplayRole: item.name}
            case 1:
                return {Qt.ItemDataRole.DisplayRole: str(item.weight)}

    # crash
    def multiData(self, index, roleDataSpan):
        item = self._items[index.row()]
        itemData = self._itemData(item, index.column())
        for roleData in roleDataSpan:
            if roleValue := itemData.get(roleData.role()):
                if existingData := roleData.data():
                    existingData.setValue(roleValue)
                else:
                    roleData.setData(roleValue)
            else:
                roleData.clearData()

    # works
    # def multiData(self, index, roleDataSpan):
    #     pass


class Widget(QTableView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setModel(Model(self))


class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setCentralWidget(Widget(self))


app = QApplication(sys.argv)
win = Window()
win.show()
app.exec()

On Tue, Aug 29, 2023 at 7:59 PM Phil Thompson <phil at riverbankcomputing.com>
wrote:

> Can you create a short complete example I can use?
>
> Thanks,
> Phil
>
> On 29/08/2023 13:40, Charles wrote:
> > I tried using multiData with this code snippet but it seems to crash
> > when
> > setting roleData.setData(...). Also I notice that the role values might
> > be
> > negative. (Btw, ic is icecream print).
> >
> >     def _itemData(self, item, col):
> >         match col.name:
> >             case 'code':
> >                 return {
> >                     Qt.DisplayRole: item.code,
> >                 }
> >             case 'earnings_chg':
> >                 return {
> >                     Qt.DisplayRole: f'{item.earnings_chg}%',
> >                 }
> >             case 'time':
> >                 return {
> >                     Qt.DisplayRole: item.time.strftime('%Y-%m-%d'),
> >                 }
> >             case 'earnings':
> >                 return {
> >                     Qt.DisplayRole: formatMoney(item.earnings),
> >                 }
> >
> >     def multiData(self, index, roleDataSpan):
> >         ic(index, roleDataSpan)
> >         item = self._items[index.row()]
> >         col = self.COLUMNS[index.column()]
> >         itemData = self._itemData(item, col)
> >         for roleData in roleDataSpan:
> >             role = roleData.role()
> >             ic(role)
> >             if value := itemData.get(role):
> >                 roleData.setData(value)
> >             else:
> >                 match role:
> >                     case Qt.FontRole:
> >                         roleData.setData(style.TABLE_FONT)
> >                     case Qt.TextAlignmentRole:
> >                         align = col.align
> >                         if align == 'C':
> >                             roleData.setData(Qt.AlignCenter)
> >                         elif align == 'R':
> >                             roleData.setData(Qt.AlignVCenter |
> > Qt.AlignRight)
> >
> > ic| earnings.py:66 in multiData()
> >     index: <PyQt6.QtCore.QModelIndex object at 0x000001D17B77D000>
> >     roleDataSpan: <PyQt6.QtCore.QModelRoleDataSpan object at
> > 0x000001D17B77D4D0>
> > ic| earnings.py:72 in multiData()- role: 6
> > ic| earnings.py:72 in multiData()- role: 7
> > ic| earnings.py:72 in multiData()- role: 9
> > ic| earnings.py:72 in multiData()- role: 10
> > ic| earnings.py:72 in multiData()- role: 1
> > ic| earnings.py:72 in multiData()- role: 0
> > ic| earnings.py:72 in multiData()- role: 8
> > ic| earnings.py:72 in multiData()- role: -948493808
> > ic| earnings.py:72 in multiData()- role: 1897532384
> > ic| earnings.py:72 in multiData()- role: 1897532384
> > ic| earnings.py:72 in multiData()- role: 2033014364
> > ic| earnings.py:72 in multiData()- role: 2
> > ic| earnings.py:72 in multiData()- role: 16777216
> > ic| earnings.py:72 in multiData()- role: 1893028080
> > ic| earnings.py:72 in multiData()- role: 1897532384
> > ic| earnings.py:72 in multiData()- role: 1897532384
> > ic| earnings.py:72 in multiData()- role: 2033014458
> > ic| earnings.py:72 in multiData()- role: 2
> > ic| earnings.py:72 in multiData()- role: 2033021932
> > ic| earnings.py:72 in multiData()- role: 3
> > ic| earnings.py:72 in multiData()- role: 524288
> > ic| earnings.py:72 in multiData()- role: 1893028080
> > ic| earnings.py:72 in multiData()- role: 1897532384
> > ic| earnings.py:72 in multiData()- role: 1897532384
> > ic| earnings.py:72 in multiData()- role: 2033022038
> > ic| earnings.py:72 in multiData()- role: 1
> > ic| earnings.py:72 in multiData()- role: 22528
> > ic| earnings.py:72 in multiData()- role: 1893028080
> >
> > On Sun, Aug 27, 2023 at 10:45 PM Phil Thompson
> > <phil at riverbankcomputing.com>
> > wrote:
> >
> >> On 14/08/2023 16:21, Jakub Fránek wrote:
> >> > Hello
> >> >
> >> > I am working on a PyQt app that features a large QTableView driven by
> a
> >> > custom QAbstractTableModel implementation. Profiling shows that even
> >> > after
> >> > heavy optimization, the program spends a lot of time calling
> >> > QAbstractItemModel.data method.
> >> >
> >> > I think that QAbstractItemModel.multiData method could improve the
> >> > performance considerably, however it seems that PyQt does not support
> >> > this
> >> > binding (since it does not even support QModelRoleDataSpan).
> >> >
> >> > My question is: is there any plan of supporting
> >> > QAbstractItemModel.multiData method in the future? If there is no such
> >> > plan
> >> > yet, I would like to cast my vote and humbly request this binding in
> >> > some
> >> > future version of PyQt.
> >>
> >> multiData() and QModelRoleSpan are implemented in the next snapshot -
> >> please test.
> >>
> >> Phil
> >>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20230829/8778386c/attachment-0001.htm>


More information about the PyQt mailing list