<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>