<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:tahoma,sans-serif"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 1 Feb 2019 at 20:50, Maurizio Berti <<a href="mailto:maurizio.berti@gmail.com">maurizio.berti@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 dir="ltr"><div dir="ltr"><div dir="ltr">To correctly support sorting for non string values you need to provide your own method.<br>Also, for numeric values ensure that the data is stored as a number and not as string. For QStandardItemModel you can achieve that by creating QStandardItems without any data value, and then set the numeric data using QStandardItem.setData(value, QtCore.Qt.DisplayValue); remember that the role must be specified, as the setData method of QStandardItem uses the UserRole + 1 role by default. This will solve the sorting for your float column.<div><div><br></div><div>To sort by date, it's better to set the QDateTime value as a custom role (>=UserRole) and store the object as it is, while you can choose to set the displayed string once you create the QStandardItems or by using an item delegate, if you need a visual representation.</div><div>After that just implement the lessThan() method of QSortFilterProxyModel, which allows to customize how the items are sorted whenever the sort() method is called.</div></div><div><br></div><div>Supposing that you're using the second column for the QDateTime items and you're using a role DateRole = QtCore.Qt.UserRole + 1:</div><div><br></div><div><div><font face="monospace, monospace">class SortModel(QtCore.QSortFilterProxyModel):</font></div><div><font face="monospace, monospace">    def lessThan(self, left, right):</font></div><div><font face="monospace, monospace">        if left.column() == right.column() and left.column() == 1:</font></div><div><font face="monospace, monospace">            return left.data(DateRole) < right.data(DateRole)</font></div><div><font face="monospace, monospace">        return QtCore.QSortFilterProxyModel.lessThan(self, left, right)</font></div></div><div><br></div><div><font face="monospace, monospace">class MyWidget(QtWidgets.QWidget):</font></div><div><font face="monospace, monospace">    def __init__(self, *args, **kwargs):</font></div><div><font face="monospace, monospace">        QtWidgets.QWidget.</font><span style="font-family:monospace,monospace">__init__(self, *args, **kwargs)</span></div><div><span style="font-family:monospace,monospace">        [...]</span><br></div><div><span style="font-family:monospace,monospace">        self.sourceModel = QtGui.QStandardItemModel()</span></div><div><span style="font-family:monospace,monospace">        self.sortModel = SortModel()</span></div><div><span style="font-family:monospace,monospace">        self.someTable.setModel(self.sortModel)</span></div><div><span style="font-family:monospace,monospace">        self.sortModel.setSourceModel(self.sourceModel)</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">    def appendFields(self):</span></div><div><span style="font-family:monospace,monospace">        floatItem = QtGui.QStandardItem()</span><br></div><div><font face="monospace, monospace">        floatItem.setData(self.getSomeFloatNumber(), QtCore.Qt.DisplayRole)</font></div><div><font face="monospace, monospace">        someDate = QtCore.QDateTime.currentDateTime()</font></div><div><font face="monospace, monospace">        item = QtGui.QStandardItem(someDate.toString())</font></div><div><font face="monospace, monospace">        item.setData(someDate, DateRole)</font></div><div><font face="monospace, monospace">        self.sourceModel.appendRow([floatItem, dateItem])</font></div><div><br></div><div>I've tested it on an old 5.7.1, but from what you are experiencing it is not a bug, but the expected behavior, since you didn't correctly implement the sorting method and/or didn't provide a correct way for Qt to interpret data for its default sorting rules.</div><div><br></div><div>Regards,</div><div>Maurizio</div><div><br></div><div><br></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Il giorno ven 1 feb 2019 alle ore 10:45 J Barchan <<a href="mailto:jnbarchan@gmail.com" target="_blank">jnbarchan@gmail.com</a>> ha scritto:<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 dir="ltr"><div dir="ltr"><div style="font-family:tahoma,sans-serif">I use Qt/PyQt 5.7, the standard distribution supplied for Ubuntu 18.04.</div><div style="font-family:tahoma,sans-serif"><br></div><div style="font-family:tahoma,sans-serif">I have a <span style="font-family:monospace,monospace">QSortFilterProxyModel</span> wrapped around a <span style="font-family:monospace,monospace">QStandardItemModel</span> as its source model.  I try to use <span style="font-family:monospace,monospace">QSortFilterProxyModel::sort()</span> to sort by column values.</div><div style="font-family:tahoma,sans-serif"><br></div><div style="font-family:tahoma,sans-serif">I have a column of Python type <span style="font-family:monospace,monospace">datetime.date</span>.  When I call the <span style="font-family:monospace,monospace">sort()</span>, there is no "warning" but <i>nothing happens</i>.  The sort does not rearrange the items at all.  They are initially "randomly" ordered in rows, and the rows simply retain their current order.  It does <i>not</i> even reorder by string value.  It is as though it simply decides they are "unorderable".</div><div style="font-family:tahoma,sans-serif"><br></div><div style="font-family:tahoma,sans-serif">When I sort instead by a Python <span style="font-family:monospace,monospace">str</span> column they <i>do</i> get reordered.  FWIW, I have another column of Python type <span style="font-family:monospace,monospace">decimal.Decimal</span> and sorting by that too does nothing, even though I think that should be convertible to <span style="font-family:monospace,monospace">float</span>/<span style="font-family:monospace,monospace">double</span>.  However, that may complicate matters so let's stick to the <span style="font-family:monospace,monospace">datetime.date</span> case, I am just mentioning it in case it's relevant.</div><div style="font-family:tahoma,sans-serif"><br></div><div style="font-family:tahoma,sans-serif">It took me a long time to realise where the problem lies.  I have a workaround: I <i>explicitly</i> change all my values in the model from <span style="font-family:monospace,monospace">datetime.date</span> to <span style="font-family:monospace,monospace">QDate(value)</span> and now it does sort.</div><div style="font-family:tahoma,sans-serif"><br></div><div style="font-family:tahoma,sans-serif">But my understanding/experience from other PyQt methods is that it does this kind of Python type -> <span style="font-family:monospace,monospace">QVariant</span> conversion for you behind the scenes itself.  I shouldn't have to change my types or write special code.</div><div style="font-family:tahoma,sans-serif"><br></div><div style="font-family:tahoma,sans-serif">Is this a bug?  Is this in my PyQt 5.7 only?</div><br>-- <br><div dir="ltr" class="gmail-m_1114654387681398389gmail-m_-5772135291516551767gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><span style="font-family:tahoma,sans-serif">Kindest,</span></div><div><span style="font-family:tahoma,sans-serif">Jonathan</span></div></div></div></div></div></div></div></div>
_______________________________________________<br>
PyQt mailing list    <a href="mailto:PyQt@riverbankcomputing.com" target="_blank">PyQt@riverbankcomputing.com</a><br>
<a href="https://www.riverbankcomputing.com/mailman/listinfo/pyqt" rel="noreferrer" target="_blank">https://www.riverbankcomputing.com/mailman/listinfo/pyqt</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail-m_1114654387681398389gmail_signature">È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi<br><a href="http://www.jidesk.net" target="_blank">http://www.jidesk.net</a></div>
</blockquote></div><div><br></div><div><div style="font-family:tahoma,sans-serif" class="gmail_default">Thank you for replying, Maurizio.  It has taken me a few days to get back to this.</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default">While I have no argument with your detailed reply (I'm quite sure you know much than I do), I do not understand <i>why</i> any of this necessary, and would appreciate any clarification.</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><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 style="font-family:tahoma,sans-serif" class="gmail_default">To correctly support sorting for non string values you need to provide your own method.</div></blockquote><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default">If I did not make it clear I would remind you of one of my findings.  I start with Python <span style="font-family:monospace,monospace">datetime.date</span> variables.  I populate the model via <span style="font-family:monospace,monospace">setData(index, dateValue)</span> (no role specified, so <span style="font-family:monospace,monospace">EditRole</span>).  At this point no sorting happens.  However, all I have to do is change that to <span style="font-family:monospace,monospace">setData(index, QDate(dateValue))</span> and it <i>does</i> then work, so no "need to provide your own method".</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default">Why is that?  From <a href="http://doc.qt.io/qt-5/qsortfilterproxymodel.html#lessThan">http://doc.qt.io/qt-5/qsortfilterproxymodel.html#lessThan</a> I am told that the sorting deals in <span style="font-family:monospace,monospace">QVariant</span> types, and <span style="font-family:monospace,monospace">QMetaType::QDate</span> is among those it handles.  Now, you know much better than I, but everywhere else I use PyQt it seems to convert between Python types and necessary <span style="font-family:monospace,monospace">QVariant</span> types invisibly and all is well, but not here?  Why not?</div><div style="font-family:tahoma,sans-serif" class="gmail_default"><br></div><div style="font-family:tahoma,sans-serif" class="gmail_default">I'm also a little lost about <span style="font-family:monospace,monospace">QStandardItem</span> vs <span style="font-family:monospace,monospace">QStandardItemModel</span>, if that's significant.  My code creates the (source) model as a <span style="font-family:monospace,monospace">QStandardItemModel</span>.  That claims to use <a href="http://doc.qt.io/qt-5/qstandarditemmodel.html#setData">http://doc.qt.io/qt-5/qstandarditemmodel.html#setData</a>,whose default <span style="font-family:monospace,monospace">role</span> is <span style="font-family:monospace,monospace">EditRole</span>.  Nowhere do I create a <span style="font-family:monospace,monospace">QStandardItem</span> explicitly, whose <a href="http://doc.qt.io/qt-5/qstandarditem.html#setData">http://doc.qt.io/qt-5/qstandarditem.html#setData</a> uses default <span style="font-family:monospace,monospace">role</span> is <span style="font-family:monospace,monospace">UserRole + 1</span>.  So now I'm not sure which I am using, though I would think only <span style="font-family:monospace,monospace">QStandardItemModel</span>?  Is this of relevance to my issue?<br></div></div><div><br></div><div><div style="font-family:tahoma,sans-serif" class="gmail_default">Thank you for any explanation.<br></div></div><br>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><span style="font-family:tahoma,sans-serif">Kindest,</span></div><div><span style="font-family:tahoma,sans-serif">Jonathan</span></div></div></div></div></div></div></div></div></div>