LINUX.ORG.RU

Как использовать QSortFilterProxyModel совместно с видом?

 , , ,


1

3

У меня есть проект, в котором до недавнего времени использовалась модель RecordTableModel, расширенная от класса QAbstractTableModel. У этой модели, помимо переопределенных стандартных методов, были добавлены дополнительные методы, которые упрощали взаимодействие вида и модели:

void RecordTableModel::setTableData(RecordTableData *rtData)
RecordTableData *RecordTableModel::getTableData(void)
int RecordTableModel::addTableData(int mode,
                                   int pos,
                                   QMap<QString, QString> fields,
                                   QString text,
                                   QMap<QString, QByteArray> files)
void RecordTableModel::removeRowsByList(QVector<int> delIdx)

Теперь пришло время сделать возможность сортировки в виде. Для этого модель RecordTableModel надо заменить на QSortFilterProxyModel. Внутри вида я создаю объект типа RecordTableModel, создаю объект типа QSortFilterProxyModel, устанавливаю для прокси-модели исходную модель через setSourceModel(), и начинаю пытаться использовать объект класса QSortFilterProxyModel:

 // Было
 recordModel=new RecordTableModel();
 setModel(recordModel);

 ...

 // Стало
 recordSourceModel=new RecordTableModel();

 recordModel=new QSortFilterProxyModel();
 recordModel->setSourceModel(recordSourceModel);

 setModel(recordModel);

Но оказывается, что класс QSortFilterProxyModel не умеет вызывать методы класса Source-модели, заданной через setSourceModel().

Как же мне теперь управляться с данными через прокси-модель? Ведь в ней недоступны методы основной модели. Я пытался применить множественное наследование, создав класс, унаследованный от RecordTableModel и QSortFilterProxyModel. Но у QAbstractTableModel (от которого унаследован RecordTableModel) и QSortFilterProxyModel есть одинаковые методы, и скомпилировать такой код не получается.

★★★★★

Но оказывается, что класс QSortFilterProxyModel не умеет вызывать методы класса Source-модели, заданной через setSourceModel().

Что?

Stil ★★★★★
()

небольшой оффтопик

Постоянно вижу как люди наследуются от Q*View... Зачем? Чем вас всех стандартные вьюхи не устраивают?

Stil ★★★★★
()
Ответ на: небольшой оффтопик от Stil

Бывают ситуации, когда надо что-то или дорисовать (и делегатом не решается) или хитро обработать клавиши/мышь, это если навскидку.

grondek
()

Но оказывается, что класс QSortFilterProxyModel не умеет вызывать методы класса Source-модели, заданной через setSourceModel().

Это какие? Если твои кастомные, то, конечно, не умеет.

А ты управляйся с данными через свою модель RecordTableModel, а проксе оставь сортировку и фильтрацию для отображения.

grondek
()
Ответ на: комментарий от grondek

А ты управляйся с данными через свою модель RecordTableModel, а проксе оставь сортировку и фильтрацию для отображения.

Модель должна позволять делать следующие вещи (когда отключена сортировка):

- Добавлять данные (в конец списка строк)
- Добавлять данные перед указанной по номеру строкой
- Добавлять данные после указанной по номеру строки
- Редактировать данные (на указанной по номеру строке)
- Удалять данные (указанную по номеру строку)
- Удалять данные по списку (список номеров строк)

Причем данные - это не то, что видно на экране, данные - это внутреннее представление модели, которое описывается отдельным классом RecordTableData. И вид, выполняя вышеуказанные действия, из модели получает ссылку на RecordTableData, и работает с этим классом. Данные между этими моделями всегда синхронны, ибо в RecordTableModel использвется ссылка на RecordTableData.

Теперь появляется третья модель класса QSortFilterProxyModel, и мне становится уже совсем непонятно, как управляться с данными.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

И вид, выполняя вышеуказанные действия, из модели получает ссылку на RecordTableData, и работает с этим классом.

Вот это идеологически неверно. Вид должен работать с моделью только через data/setData

annulen ★★★★★
()
Ответ на: комментарий от annulen

Вот это идеологически неверно. Вид должен работать с моделью только через data/setData

Ну и как ты будешь через data/setData выполнять действия:

- Добавлять данные (в конец списка строк)
- Добавлять данные перед указанной по номеру строкой
- Добавлять данные после указанной по номеру строки
- Редактировать данные (на указанной по номеру строке)
- Удалять данные (указанную по номеру строку)
- Удалять данные по списку (список номеров строк)

?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Если это надо делать именно из вида (пользователь редактирует таблицу через UI), то вставку через insertRows, удаление через removeRows, редактирование через setData. А если эти операции происходят в коде бизнес-логики, то вид вообще не причем.

annulen ★★★★★
()
Ответ на: комментарий от Xintrea

- Добавлять данные (в конец списка строк)
- Добавлять данные перед указанной по номеру строкой
- Добавлять данные после указанной по номеру строки
- Удалять данные (указанную по номеру строку)
- Удалять данные по списку (список номеров строк)

insertRow()/insertRows()
removeRow()/removeRows()

- Редактировать данные (на указанной по номеру строке)

А тут-то чем setData не устраивает?

m0rph ★★★★★
()
Последнее исправление: m0rph (всего исправлений: 2)
Ответ на: комментарий от annulen

Вот это идеологически неверно. Вид должен работать с моделью только через data/setData

Кстати, на тостере рекомендуют строго противоположное:

А Вам и не нужно управлять данными через прокси-модель. Делайте это напрямую с RecordTableModel, а QSortFilterProxyModel будет лишь сортировать.

Поймите, данные должны храниться только в модели (т.е. в RecordTableModel) и именно она должна с ними работать, и больше никто. QSortFilterProxyModel в таком случае будет толкьо менять формат отображения этих данных, но не сами данные.

https://toster.ru/q/216166?e=1961590#answer_item_582306

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Есть две совершенно разные задачи: управление данными из бизнес логики приложения (модель) и из пользовательского интерфейса (контроллер, вид)

annulen ★★★★★
()

У меня есть проект, в котором до недавнего времени использовалась модель RecordTableModel, расширенная от класса QAbstractTableModel

нормальный подход. в чем проблема создать прокси свой и в проекте использовать связку

View -> MyProxy -> MyModel?

MikeDM ★★★★★
()

У QSortFilterProxyModel есть метод sourceModel(), который возвращает указатель на исходную модель, т.е. вашу RecordTableModel. Можно сделать: dynamic_cast<RecordTableModel*>(recordModel->sourceModel()) и вызывать ваши методы. Но насчет архитектуры и правда стоит задуматься.

midvik
()

А что тебе мешает напрямую использовать эти методы? Главное помнить, что твоя модель должна вызывать beginInsertRows/endInsertRows, beginRemoveRows/endRemoveRows, beginResetModel/endResetModel и dataChanged в соответствующих методах. Ну а вообще тебе выше сказали, что так лучше не делать

Torvus
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.