<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small">Adding __iter__ to QModelRoleDataSpan also works</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small">QModelRoleDataSpan.__iter__ = lambda self: (self[i] for i in range(self.length()))</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"> def multiData(self, index, roleDataSpan):<br> item = self._items[index.row()]<br> itemData = self._itemData(item, index.column())<br> for roleData in roleDataSpan:<br> if roleValue := itemData.get(roleData.role()):<br> roleData.setData(roleValue)<br> else:<br> roleData.clearData()</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Aug 30, 2023 at 1:41 AM Charles <<a href="mailto:peacech@gmail.com">peacech@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small">Apparently the problem is with using python iteration over the QModelRoleDataSpan object (does it supports python iteration)?</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small">This code instead works fine</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"> def multiData(self, index, roleDataSpan):<br> item = self._items[index.row()]<br> itemData = self._itemData(item, index.column())<br> for i in range(roleDataSpan.length()):<br> roleData = roleDataSpan[i]<br> if roleValue := itemData.get(roleData.role()):<br> roleData.setData(roleValue)<br> else:<br> roleData.clearData()</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 29, 2023 at 8:17 PM Charles <<a href="mailto:peacech@gmail.com" target="_blank">peacech@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small">Hi Phil, here is an example standalone code</div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small"><br></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif;font-size:small">import sys<br>from dataclasses import dataclass<br><br>from PyQt6.QtCore import QAbstractTableModel, Qt<br>from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView<br><br><br>@dataclass<br>class Item:<br> name: str<br> weight: int<br><br><br>class Model(QAbstractTableModel):<br> def __init__(self, parent=None):<br> super().__init__(parent)<br> self._items = [Item('A', 10), ('B', 11)]<br><br> def rowCount(self, index):<br> return len(self._items)<br><br> def columnCount(self, index):<br> return 2<br><br> def _itemData(self, item, column):<br> match column:<br> case 0:<br> return {Qt.ItemDataRole.DisplayRole: <a href="http://item.name" target="_blank">item.name</a>}<br> case 1:<br> return {Qt.ItemDataRole.DisplayRole: str(item.weight)}<br><br> # crash<br> def multiData(self, index, roleDataSpan):<br> item = self._items[index.row()]<br> itemData = self._itemData(item, index.column())<br> for roleData in roleDataSpan:<br> if roleValue := itemData.get(roleData.role()):<br> if existingData := roleData.data():<br> existingData.setValue(roleValue)<br> else:<br> roleData.setData(roleValue)<br> else:<br> roleData.clearData()<br><br> # works<br> # def multiData(self, index, roleDataSpan):<br> # pass<br><br><br>class Widget(QTableView):<br> def __init__(self, parent=None):<br> super().__init__(parent)<br> self.setModel(Model(self))<br><br><br>class Window(QMainWindow):<br> def __init__(self):<br> super().__init__()<br> self.setCentralWidget(Widget(self))<br><br><br>app = QApplication(sys.argv)<br>win = Window()<br>win.show()<br>app.exec()<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 29, 2023 at 7:59 PM Phil Thompson <<a href="mailto:phil@riverbankcomputing.com" target="_blank">phil@riverbankcomputing.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Can you create a short complete example I can use?<br>
<br>
Thanks,<br>
Phil<br>
<br>
On 29/08/2023 13:40, Charles wrote:<br>
> I tried using multiData with this code snippet but it seems to crash <br>
> when<br>
> setting roleData.setData(...). Also I notice that the role values might <br>
> be<br>
> negative. (Btw, ic is icecream print).<br>
> <br>
> def _itemData(self, item, col):<br>
> match <a href="http://col.name" rel="noreferrer" target="_blank">col.name</a>:<br>
> case 'code':<br>
> return {<br>
> Qt.DisplayRole: item.code,<br>
> }<br>
> case 'earnings_chg':<br>
> return {<br>
> Qt.DisplayRole: f'{item.earnings_chg}%',<br>
> }<br>
> case 'time':<br>
> return {<br>
> Qt.DisplayRole: item.time.strftime('%Y-%m-%d'),<br>
> }<br>
> case 'earnings':<br>
> return {<br>
> Qt.DisplayRole: formatMoney(item.earnings),<br>
> }<br>
> <br>
> def multiData(self, index, roleDataSpan):<br>
> ic(index, roleDataSpan)<br>
> item = self._items[index.row()]<br>
> col = self.COLUMNS[index.column()]<br>
> itemData = self._itemData(item, col)<br>
> for roleData in roleDataSpan:<br>
> role = roleData.role()<br>
> ic(role)<br>
> if value := itemData.get(role):<br>
> roleData.setData(value)<br>
> else:<br>
> match role:<br>
> case Qt.FontRole:<br>
> roleData.setData(style.TABLE_FONT)<br>
> case Qt.TextAlignmentRole:<br>
> align = col.align<br>
> if align == 'C':<br>
> roleData.setData(Qt.AlignCenter)<br>
> elif align == 'R':<br>
> roleData.setData(Qt.AlignVCenter |<br>
> Qt.AlignRight)<br>
> <br>
> ic| earnings.py:66 in multiData()<br>
> index: <PyQt6.QtCore.QModelIndex object at 0x000001D17B77D000><br>
> roleDataSpan: <PyQt6.QtCore.QModelRoleDataSpan object at<br>
> 0x000001D17B77D4D0><br>
> ic| earnings.py:72 in multiData()- role: 6<br>
> ic| earnings.py:72 in multiData()- role: 7<br>
> ic| earnings.py:72 in multiData()- role: 9<br>
> ic| earnings.py:72 in multiData()- role: 10<br>
> ic| earnings.py:72 in multiData()- role: 1<br>
> ic| earnings.py:72 in multiData()- role: 0<br>
> ic| earnings.py:72 in multiData()- role: 8<br>
> ic| earnings.py:72 in multiData()- role: -948493808<br>
> ic| earnings.py:72 in multiData()- role: 1897532384<br>
> ic| earnings.py:72 in multiData()- role: 1897532384<br>
> ic| earnings.py:72 in multiData()- role: 2033014364<br>
> ic| earnings.py:72 in multiData()- role: 2<br>
> ic| earnings.py:72 in multiData()- role: 16777216<br>
> ic| earnings.py:72 in multiData()- role: 1893028080<br>
> ic| earnings.py:72 in multiData()- role: 1897532384<br>
> ic| earnings.py:72 in multiData()- role: 1897532384<br>
> ic| earnings.py:72 in multiData()- role: 2033014458<br>
> ic| earnings.py:72 in multiData()- role: 2<br>
> ic| earnings.py:72 in multiData()- role: 2033021932<br>
> ic| earnings.py:72 in multiData()- role: 3<br>
> ic| earnings.py:72 in multiData()- role: 524288<br>
> ic| earnings.py:72 in multiData()- role: 1893028080<br>
> ic| earnings.py:72 in multiData()- role: 1897532384<br>
> ic| earnings.py:72 in multiData()- role: 1897532384<br>
> ic| earnings.py:72 in multiData()- role: 2033022038<br>
> ic| earnings.py:72 in multiData()- role: 1<br>
> ic| earnings.py:72 in multiData()- role: 22528<br>
> ic| earnings.py:72 in multiData()- role: 1893028080<br>
> <br>
> On Sun, Aug 27, 2023 at 10:45 PM Phil Thompson <br>
> <<a href="mailto:phil@riverbankcomputing.com" target="_blank">phil@riverbankcomputing.com</a>><br>
> wrote:<br>
> <br>
>> On 14/08/2023 16:21, Jakub Fránek wrote:<br>
>> > Hello<br>
>> ><br>
>> > I am working on a PyQt app that features a large QTableView driven by a<br>
>> > custom QAbstractTableModel implementation. Profiling shows that even<br>
>> > after<br>
>> > heavy optimization, the program spends a lot of time calling<br>
>> > QAbstractItemModel.data method.<br>
>> ><br>
>> > I think that QAbstractItemModel.multiData method could improve the<br>
>> > performance considerably, however it seems that PyQt does not support<br>
>> > this<br>
>> > binding (since it does not even support QModelRoleDataSpan).<br>
>> ><br>
>> > My question is: is there any plan of supporting<br>
>> > QAbstractItemModel.multiData method in the future? If there is no such<br>
>> > plan<br>
>> > yet, I would like to cast my vote and humbly request this binding in<br>
>> > some<br>
>> > future version of PyQt.<br>
>> <br>
>> multiData() and QModelRoleSpan are implemented in the next snapshot -<br>
>> please test.<br>
>> <br>
>> Phil<br>
>> <br>
</blockquote></div>
</blockquote></div>
</blockquote></div>