Missing QAbstractItemModel.multiData binding
Charles
peacech at gmail.com
Tue Aug 29 19:41:01 BST 2023
Apparently the problem is with using python iteration over the
QModelRoleDataSpan object (does it supports python iteration)?
This code instead works fine
def multiData(self, index, roleDataSpan):
item = self._items[index.row()]
itemData = self._itemData(item, index.column())
for i in range(roleDataSpan.length()):
roleData = roleDataSpan[i]
if roleValue := itemData.get(roleData.role()):
roleData.setData(roleValue)
else:
roleData.clearData()
On Tue, Aug 29, 2023 at 8:17 PM Charles <peacech at gmail.com> wrote:
> 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/20230830/96b12d11/attachment.htm>
More information about the PyQt
mailing list