Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Павелъ от Ноябрь 22, 2017, 13:30



Название: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 13:30
Доброго времени суток.

Когда сортируешь списки, есть замечательная штука qSort, в которую последним аргументом можно передать лямбда-функцию, и сортировка пойдёт по собственному алгоритму.

У меня есть QTreeView, а в ней модель, унаследованная от QStandardItemModel.

Хочу отсортировать детей в одном из айтемов в модели Дерева.

Но, в методе sortChildren жёстко прописывается порядок сортировки QSortOrder, никаких lessThan и lambda не передашь :'(. В результате алгоритм сортирует айтемы по алфавиту, а мне надо по величине численных значений. Как это реализовать?

Нашёл, что надо копать вокруг QSortFilterProxyModel, но как сделать сортировку по числовым значениям с помощью этого класса, так и не понял.

Мои неудачные попытки реализовать сортировку:

Код:
segmentItem->sortChildren(0,[=](QModelIndex &s1,QModelIndex &s2){
        int first = CommonFunctions::getEndAddressPart(s1.data().toString()).toInt();
        int second = CommonFunctions::getEndAddressPart(s2.data().toString()).toInt();

        return first < second;

    });
так не работает.


Код:
qSort(segmentItem->child(0),segmentItem->child(segmentItem->rowCount() - 1),[=](SegmentStandardItem *&s1,SegmentStandardItem *&s2){
        int first = CommonFunctions::getEndAddressPart(s1->text()).toInt();
        int second = CommonFunctions::getEndAddressPart(s2->text()).toInt();

        return first < second;
    });
так тоже не работает.

Код:
    segmentItem->sortChildren(0,Qt::AscendingOrder);
так сортирует по алфавиту.


SegmentStandardItem  унаследован от QStandardItem

Спасибо.


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: __Heaven__ от Ноябрь 22, 2017, 13:43
А метод data(Qt::DisplayRole) возвращает строку или значение в QVariantе?
Свойство sortRole может быть как-либо использовано для сортировки.


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 13:49
А метод data(Qt::DisplayRole) возвращает строку или значение в QVariantе?
Свойство sortRole может быть как-либо использовано для сортировки.

Я не очень понял о чём идёт речь.
У меня метод data вызывается только в qmodelindex, но там всё равно ничего не будет работать. Ибо нет возможности добавить lessThan


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 13:59
setsortrole тоже не вариант . Этот метод ставится для всей модели, а мне нужно только для айтемов второго уровня


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: __Heaven__ от Ноябрь 22, 2017, 14:26
Редко работал с QStandardItemModel
Забыл, как она работает.
Она принимает текстовые значения, значит и возвращает их же, скорее всего.

Перейти на QAbstractItemModel не вариант?


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 14:46
Редко работал с QStandardItemModel
Забыл, как она работает.
Она принимает текстовые значения, значит и возвращает их же, скорее всего.

Перейти на QAbstractItemModel не вариант?f


Там сортировка по-другому реализована?


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Авварон от Ноябрь 22, 2017, 15:44
Там сортировка пишется руками:)


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 16:20
Там сортировка пишется руками:)

И что, самому пилить быструю сортировку? Неужели нет шаблона никакого?


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Авварон от Ноябрь 22, 2017, 17:22
Норкоман, штолле?


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: __Heaven__ от Ноябрь 22, 2017, 17:35
Там сортировка пишется руками:)

И что, самому пилить быструю сортировку? Неужели нет шаблона никакого?
Можно воспользоваться qSort, например, внутри метода :)


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 18:14
Там сортировка пишется руками:)

И что, самому пилить быструю сортировку? Неужели нет шаблона никакого?
Можно воспользоваться qSort, например, внутри метода :)


Это как? В childrensort я могу подать только номер столбца и sortorder.


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 22, 2017, 18:33
Понял, о чём идёт речь. А нужен ли обязательно абстрактный класс. Нельзя что ли в QStandardItem реализовать ещё одну функцию сортировки потомков? И как я воспользуюсь qSort? Потомки должны храниться в виде списка? qSort сортирует списки.


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: __Heaven__ от Ноябрь 23, 2017, 10:10
Можно попробовать немного повелосипедить.
Есть метод QStandardItem::takeRow, который позволит забрать из модели сортируемые строки и сформировать список этих строк в памяти. Далее этот список отсортировать как требуется и вернуть строки прежнему родителю.
Думаю, должно получиться


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 23, 2017, 11:25
Можно попробовать немного повелосипедить.
Есть метод QStandardItem::takeRow, который позволит забрать из модели сортируемые строки и сформировать список этих строк в памяти. Далее этот список отсортировать как требуется и вернуть строки прежнему родителю.
Думаю, должно получиться

Значит, я формирую список строк. После формирования и сортировки списка мне нужно очистить модель и опять в цикле сделать insertRow()? Дочерние айтемы надеюсь потащутся вместе с родителями?


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Павелъ от Ноябрь 23, 2017, 13:43
Можно попробовать немного повелосипедить.
Есть метод QStandardItem::takeRow, который позволит забрать из модели сортируемые строки и сформировать список этих строк в памяти. Далее этот список отсортировать как требуется и вернуть строки прежнему родителю.
Думаю, должно получиться

Спасибо, работает!

takeRow() убирает ещё строку, так что не пришлось чистить айтем.


Название: Re: sortChildren в QStandardItem по собственному алгоритму.
Отправлено: Авварон от Ноябрь 23, 2017, 14:59
Можно попробовать немного повелосипедить.
Есть метод QStandardItem::takeRow, который позволит забрать из модели сортируемые строки и сформировать список этих строк в памяти. Далее этот список отсортировать как требуется и вернуть строки прежнему родителю.
Думаю, должно получиться

Это дичайший говнокод, потому что каждый takeRow вызывает beginRemoveRows/endRemoveRows, что приводит к N изменениям вью (где N - количество рядов). Побочным эффектом является инвалидация всех persistent indexes (визуально, например, пропадёт выделенная строка)
Sort же вызывает layoutAboutToBeChanged/layoutChanged которые меняют persistent indexes (говорят, раньше была выделена 10я строка, а теперь 90я) + вызывают ОДНО обновление вью.

Т.е. вместо алгоритма со сложностью O(1) предлагается сложность O(N).
Но работать будет:)