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