[PyQt] QSortFilterProxyModel::sort() not sorting on column types

J Barchan jnbarchan at gmail.com
Wed Feb 6 14:13:00 GMT 2019


On Wed, 6 Feb 2019 at 13:33, Maurizio Berti <maurizio.berti at gmail.com>
wrote:

> If I did not make it clear I would remind you of one of my findings.  I
>> start with Python datetime.date variables.  I populate the model via setData(index,
>> dateValue) (no role specified, so EditRole).  At this point no sorting
>> happens.  However, all I have to do is change that to setData(index,
>> QDate(dateValue)) and it *does* then work, so no "need to provide your
>> own method".
>>
>
>> Why is that?  From
>> http://doc.qt.io/qt-5/qsortfilterproxymodel.html#lessThan I am told that
>> the sorting deals in QVariant types, and QMetaType::QDate 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 QVariant
>> types invisibly and all is well, but not here?  Why not?
>>
>>
> Well, that's interesting: I've always assumed that the DisplayRole
> wouldn't accept data other than strings and numbers, but you made me
> realize that it can actually store any data that "supports" printable form
> (which QDate/Time do). Of course, this could be a small issue if you want a
> different string format for dates, but if the default one suits your needs,
> that's fine.
> Since lessThan supports a small set of QVariant types (including
> QDate/Time) and we can use that QVariant type as a Display role, it's good
> enough.
> Besides that, I tried to use setData with random QDateTimes converted
> QDate using their date() method, and it seems to work fine, without using
> QDate(dateValue) you mentioned.
> To be clear, I tested with this code:
>
> sourceModel.setData(
>     sourceModel.index(row, 0),
>
> QtCore.QDateTime().currentDateTime().addDays(-randrange(30)).addSecs(-randrange(86400)).date())
>
> I'm using an old Qt 5.7.1, it's possible that it's a regression, have you
> checked up on QtBugs?
>
>
>
>> I'm also a little lost about QStandardItem vs QStandardItemModel, if
>> that's significant.  My code creates the (source) model as a
>> QStandardItemModel.  That claims to use
>> http://doc.qt.io/qt-5/qstandarditemmodel.html#setData,whose default role
>> is EditRole.  Nowhere do I create a QStandardItem explicitly, whose
>> http://doc.qt.io/qt-5/qstandarditem.html#setData uses default role is UserRole
>> + 1.  So now I'm not sure which I am using, though I would think only
>> QStandardItemModel?  Is this of relevance to my issue?
>>
>
> Well, I've always used empty models at start and fill them as needed,
> since I mostly use dynamic models or prefer to create data in this way. But
> that's one way.
> It doesn't change much from creating a model (even specifying the size, if
> you can) and then create new rows/columns and setting the data directly
> from the model.
> In this case, the QStandardItems do not exist until the internal indexes
> are created (trying to access any index is enough, for example by setting
> or reading data): if you try to access a item(0, 0) on a new
> QStandardItemModel with a specified size, it will return None. If you try a
> itemFromIndex(model.index(0,0)) it will return an item.
> That said, I don't think it would change much in your case, as soon as you
> always use the right role when setting data. I think that the default
> UserRole + 1 of item.setData is just for convenience, but since you always
> use the model.setData methods that wouldn't be an issue anyway.
>
> Maurizio
>
> --
> È difficile avere una convinzione precisa quando si parla delle ragioni
> del cuore. - "Sostiene Pereira", Antonio Tabucchi
> http://www.jidesk.net
>

Hi Maurizio,

Thank you again for your interest in replying.

Besides that, I tried to use setData with random QDateTimes converted QDate
> using their date() method, and it seems to work fine, without using
> QDate(dateValue) you mentioned.
>

This does not matter now, in that I have a workaround, but I'll ask you one
more time.  The example you give talks about converting QDateTimes to QDates.
Please forget about QDateTime, that is not the issue I am asking about.  As
long as your original code only uses the Qt native types like QDate or
QDateTime there will be no problem sorting.  I understand that.

My code uses the *Python* types from the datetime module.  datetime.date is
a Python date type.  In all other places I have made PyQt calls it always
correctly converts between, say, Python type datetime.date and Qt type QDate,
in either direction, as necessary.  I do not have to do anything special in
my code.  The PyQt wrappers for arguments etc. are doing it for me.  This
is a huge (good) point about PyQt.

In the sole case of QSortFilterProxyModel.sort(), however, if I fill my
model via:

model.setData(row, col, something_of_type_datetime_date)
>

everything about it works fine *except* for attempting to call the sort,
which seems to do nothing to alter the order.  If I change my model just so
that I used:

model.setData(row, col, QDate(something_of_type_datetime_date))
>

then the sorting also works.

The *only* question I do not understand/would like answered is: why do I
have to use QDate and not datetime.date in the model to make just
QSortFilterProxyModel::sort() work, when everything other than that works
fine with datetime.date?  Why does PyQt auto-conversion between Python
datetime.date and Qt QDate work everywhere other than during
QSortFilterProxyModel.sort()?


-- 
Kindest,
Jonathan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190206/3edd6c6c/attachment-0001.html>


More information about the PyQt mailing list