Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Пантер от Август 26, 2007, 18:07



Название: Сортировка в модели
Отправлено: Пантер от Август 26, 2007, 18:07
В общем все началось давным давно....  :)
Использую QStandardItemModel и QTreeView, загоняю в модель имена файлов, расширения, даты, в общем самодельный файловый менеджер. Понадобилась сортировка, после прочтения форума понял, что нужно действовать через QSortFilterProxyModel. После прочтения ассистента пришел к такой связке:
1. Наследую класс QSortFilterProxyModel.
2. Переписываю lessThan.
3. Подключаю QStandardItemModel к QSortFilterProxyModel.
4. Подключаю QSortFilterProxyModel к QTreeView.
Собственно несколько вопросов:
1. Праильно ли сделано, просто какое-то очень неудобное подключение модели через модель. :)
2. Как сделать дирректории всегда вверху? Т.е. тут вопрос в том, где достать тип сортировки(сверху вниз или наоборот). Искал в модели, но там это встречается только в sort, но переопределяя эту функцию я гроблю всю сортировку. :(


Название: Re: Сортировка в модели
Отправлено: vaprele07 от Август 27, 2007, 01:33
Код:
bool QSortFilterProxyModel::lessThan ( const QModelIndex & left, const QModelIndex & right ) const 
{
  ...
  if (leftType != rightType) return (leftType == dir); // или return (leftType == file); вверх-вниз
    else return QString::localeAwareCompare(leftString, rightString) < 0;
}

Забыл: насчёт первого да правильно QStandardItemMode это как БД, а QSortFilterProxyModel как SQL запрос


Название: Re: Сортировка в модели
Отправлено: denka от Август 27, 2007, 09:38
А почему не воспользовался QDirModel там и сортировка вроде как есть и филтры?


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 27, 2007, 11:38
Код:
bool QSortFilterProxyModel::lessThan ( const QModelIndex & left, const QModelIndex & right ) const 
{
  ...
  if (leftType != rightType) return (leftType == dir); // или return (leftType == file); вверх-вниз
    else return QString::localeAwareCompare(leftString, rightString) < 0;
}

Забыл: насчёт первого да правильно QStandardItemMode это как БД, а QSortFilterProxyModel как SQL запрос
Этот код есть в ассисетнте. Вопрос был в другом: как узнать ТЕКУЩИЙ тип сортировки (вверх-вниз)? Ваш код работать не будет, так как дирректории будут или все вверху, или все внизу.
А почему не воспользовался QDirModel там и сортировка вроде как есть и филтры?
Во-первых недавно я поднимал вопрос о баге с pagefile.sys, а во-вторых скорость загрузки не устраивает и еще кое какие мелочи.


Название: Re: Сортировка в модели
Отправлено: Emc от Август 27, 2007, 12:02
собственная сортировка устанавливается через setSortRole()


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 27, 2007, 12:11
собственная сортировка устанавливается через setSortRole()
На сколько я понял из ассистента, setSortRole() к этому никаким боком не относится. Посмотри значения enum Qt::ItemDataRole там ничего о порядке сортировки.


Название: Re: Сортировка в модели
Отправлено: vaprele07 от Август 27, 2007, 13:38
Поряд собственной сортировки что и когда ты задаешь сам путем переопределения lessThan
if (leftType != rightType) return (leftType == dir); // или return (leftType == file); вверх-вниз
в этой строчке ты сортируешь индексы по типам т.е. если типы не совпадают значит что-то из двух файл, а что-то папка при этом return (leftType == dir) директории вверху, при этом return (leftType == file) внизу, если типы совпадают то выполняется:
else return QString::localeAwareCompare(leftString, rightString) < 0; здесь может быть любая другая функция сравнения хоть по дате хоть по мимэ типу...
setSortRole() сортировка по ролям, допустим нужно тебе сортировать по тултипам, статустипам, декорациям.

кстати если тебе нужна сортировка типа папка-файл вверх-вниз без изменения стандартной логики:

Код:
bool MySortFilterProxyModel::lessThan ( const QModelIndex & left, const QModelIndex & right ) const 
{
  ...
  if (leftType != rightType) return (leftType == (MySortType == dirAbove)?dir:file);
    else return QSortFilterProxyModel::lessThan(left, right);
}


Название: Re: Сортировка в модели
Отправлено: Emc от Август 27, 2007, 14:00
setSortRole() относится к этому напрямую
самый примитивный вариант, создаешь собственную роль - в случае папки MyRole = "AAA_+DisplayRole" в случае файла MyRole = "DisplayRole".
//
setSortRole(MyRole);
sort(0);
//
собственно всё


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 27, 2007, 16:52
Да я не об этом. Есть колонка имен с номером 0. Щелкаем по ней один раз и сортировка происходит по возрастанию, щелкаем второй - по убыванию. Мне нужно знать, по возрастанию или убыванию сортировка, потому что lessThan в разных случаях интерпретируется по разному, т.е. логически умножается на порядок сортировки.


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 27, 2007, 17:54
Вот ответ, наверное. Завтра буду копать.
http://websvn.kde.org/trunk/KDE/kdelibs/kfile/kdirsortfilterproxymodel.cpp
http://websvn.kde.org/trunk/KDE/kdelibs/kfile/kdirsortfilterproxymodel.h


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 28, 2007, 11:26
Облом. Все не то. Вот мой код:
Код:
QVariant UpData = sourceModel()->data(sourceModel()->index(qmiUp.row(),2));
QVariant DownData = sourceModel()->data(sourceModel()->index(qmiDown.row(),2));

if ((UpData.toString()=="-=DIR=-") && (DownData.toString()!="-=DIR=-"))
{
return true;
}
else
if ((UpData.toString()!="-=DIR=-") && (DownData.toString()=="-=DIR=-"))
{
return false;
}
В итоге папки отдельно от файлов, но то вверху, то внизу. Решением послужило бы
Код:
QVariant UpData = sourceModel()->data(sourceModel()->index(qmiUp.row(),2));
QVariant DownData = sourceModel()->data(sourceModel()->index(qmiDown.row(),2));

if ((UpData.toString()=="-=DIR=-") && (DownData.toString()!="-=DIR=-"))
{
return true && order;
}
else
if ((UpData.toString()!="-=DIR=-") && (DownData.toString()=="-=DIR=-"))
{
return false && order;
}
Где order есть Qt::SortOrder (AscendingOrder или DescendingOrder). Но как этот order достать?????


Название: Re: Сортировка в модели
Отправлено: denka от Август 29, 2007, 10:00
Можно так:
Код:
class MySortModel : public QSortFilterProxyModel
{
public:
MySortModel( QObject * parent = 0 );
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const;
void sort( int column, Qt::SortOrder order = Qt::AscendingOrder );
private:
Qt::SortOrder m_order;
};
Код:
void MySortModel::sort( int column, Qt::SortOrder order )
{
m_order = order;
QSortFilterProxyModel::sort( column, order );
}
Код:
bool MySortModel::lessThan( const QModelIndex &l, const QModelIndex &r ) const
{
...
if ( ltype == rtype )
return QString::localeAwareCompare( lname, rname ) < 0;
else if ( ltype == "dir" )
return m_order == Qt::AscendingOrder;
return m_order != Qt::AscendingOrder;
}

ltype и rtype это или каталог или файл, соответственно левый и правый индекс :)


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 29, 2007, 11:34
А ты пробовал этот код? Просто у меня он не заработал. Из sort ты вызываешь QSortFilterProxyModel::sort( column, order ); но QSortFilterProxyModel - это не твоя модель, и lessThan у нее соответсвенно не твой. :(


Название: Re: Сортировка в модели
Отправлено: denka от Август 29, 2007, 11:43
У меня все работает. Правда я не пользовался QStandardItemModel, но ведь это не меняет дела. Если хочеш вышлю на мыло исходники.


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 29, 2007, 11:46
Буду очень рад.
panter.dsd@gmail.com
Только можешь в ближайшие 10 минут кинуть, а то на работу...


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 29, 2007, 11:49
А какой моделью ты пользовался? И почему?


Название: Re: Сортировка в модели
Отправлено: denka от Август 29, 2007, 12:00
Отправил. Давай в аську чтоб не флудить)


Название: Re: Сортировка в модели
Отправлено: Пантер от Август 29, 2007, 18:32
Все решено, спасибо den'ka. Признаю, что был глуп, просто не так давно программирую. Спасибо всем за помощь. Тему можно закрыть.