Russian Qt Forum
Ноябрь 24, 2024, 02:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QSortFilterProxyModel и insertRow  (Прочитано 8351 раз)
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« : Сентябрь 05, 2016, 19:13 »

Почему почему в QSortFilterProxyModel нельзя использовать insertRow()
Записан
PimenS
Крякер
****
Offline Offline

Сообщений: 371


Просмотр профиля
« Ответ #1 : Сентябрь 05, 2016, 19:45 »

Потому что QSortFilterProxyModel не хранит данные, а работает с данными находящимися в установленной QAbstractItemModel *QAbstractProxyModel::sourceModel() const
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #2 : Сентябрь 05, 2016, 21:02 »

Логично.
Тогда как мне создать промежуточную модель, чтобы
можно в нее добавлять данные (несколько записей), а по нажатию кнопки
все скинуть в базу??? Непонимающий
« Последнее редактирование: Сентябрь 05, 2016, 21:35 от demaker » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #3 : Сентябрь 06, 2016, 08:49 »

Наследуйтесь от QAbstractItemModel, помещайте внутрь другую модель  и реализуйте виртуальные методы с учетом вложенной модели. Должна получиться реализация похожая на QSortFilterProxyModel, только с вашей логикой добавления/редактирования/удаления элементов.
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #4 : Сентябрь 06, 2016, 16:02 »

Почему почему в QSortFilterProxyModel нельзя использовать insertRow()
А почему нельзя? Вроде и можно и работает, специально проверил у себя.

Цитировать
Потому что QSortFilterProxyModel не хранит данные, а работает с данными находящимися в установленной QAbstractItemModel *QAbstractProxyModel::sourceModel() const
Ну и что, вот в своей реализации InsertRows она и вызовет InsertRows исходной модели - в этом и суть прокси модели работать как исходная с возможностью сортировки и фильтрации.

Цитировать
Наследуйтесь от QAbstractItemModel, помещайте внутрь другую модель  и реализуйте виртуальные методы с учетом вложенной модели. Должна получиться реализация похожая на QSortFilterProxyModel, только с вашей логикой добавления/редактирования/удаления элементов.
QSortFilterProxyModel итак наследник QAbstractItemModel и именно для таких целей и был придумал, мне кажется надо его использовать, а не изобретать велосипед.
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #5 : Сентябрь 06, 2016, 16:44 »

Почему почему в QSortFilterProxyModel нельзя использовать insertRow()
А почему нельзя? Вроде и можно и работает, специально проверил у себя.

Делаю так не работает
Код
C++ (Qt)
void DataBaseFilterModel::insertData()
{
   int lastRow = rowCount(QModelIndex());
   qDebug()<<lastRow;
   qDebug()<<insertRows(lastRow,1);//?????????????????????????????
}
 
В дебаге false
« Последнее редактирование: Сентябрь 06, 2016, 17:56 от demaker » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #6 : Сентябрь 06, 2016, 18:02 »

Наследуйтесь от QAbstractItemModel, помещайте внутрь другую модель  и реализуйте виртуальные методы с учетом вложенной модели. Должна получиться реализация похожая на QSortFilterProxyModel, только с вашей логикой добавления/редактирования/удаления элементов.

Так же insertRow выдает false;

Получается что мне нужно выгружать данные из в промежуточную модель в какой-то буффер
и добавлять туда при инсерте еще одну запись.
Так?   Непонимающий
« Последнее редактирование: Сентябрь 06, 2016, 19:13 от demaker » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #7 : Сентябрь 06, 2016, 20:42 »

Код:
bool QSortFilterProxyModel::insertRows(int row, int count, const QModelIndex &parent)
{
    Q_D(QSortFilterProxyModel);
    if (row < 0 || count <= 0)
        return false;
    QModelIndex source_parent = mapToSource(parent);
    if (parent.isValid() && !source_parent.isValid())
        return false;
    QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
    if (row > m->source_rows.count())
        return false;
    int source_row = (row >= m->source_rows.count()
                      ? m->source_rows.count()
                      : m->source_rows.at(row));
    return d->model->insertRows(source_row, count, source_parent);
}

Обратите внимание на последнюю строчку - как я и говорил, прокси просто через свою приватную часть вызывает метод InsertRows исходной модели.
У Вас что за модель используется в качестве исходной для прокси? В ней то реализовано InsertRows ?
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #8 : Сентябрь 06, 2016, 21:16 »

Код:
bool QSortFilterProxyModel::insertRows(int row, int count, const QModelIndex &parent)
{
    Q_D(QSortFilterProxyModel);
    if (row < 0 || count <= 0)
        return false;
    QModelIndex source_parent = mapToSource(parent);
    if (parent.isValid() && !source_parent.isValid())
        return false;
    QSortFilterProxyModelPrivate::Mapping *m = d->create_mapping(source_parent).value();
    if (row > m->source_rows.count())
        return false;
    int source_row = (row >= m->source_rows.count()
                      ? m->source_rows.count()
                      : m->source_rows.at(row));
    return d->model->insertRows(source_row, count, source_parent);
}

Обратите внимание на последнюю строчку - как я и говорил, прокси просто через свою приватную часть вызывает метод InsertRows исходной модели.
У Вас что за модель используется в качестве исходной для прокси? В ней то реализовано InsertRows ?

У меня класс унаследованный от  QSqlQueryModel.
А инсерт у меня в нем реализован свой и делается через sql зарос к базе.
« Последнее редактирование: Сентябрь 06, 2016, 21:19 от demaker » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #9 : Сентябрь 06, 2016, 21:24 »

Цитировать
У меня класс унаследованный от  QSqlQueryModel.
А инсерт у меня в нем реализован свой и делается через sql зарос к базе.
Хорошо в этой вашей своей модели InsertRows виртуальный переопределен или свой какой нибудь метод типа "AddRow" для вставки новых записей?

Очевидно второе и тогда понятно почему у вас InsertRows возвращает false. QSqlQueryModel - только для чтения, в ней не реализован InsertRows, она унаследована от QSqlTableModel  в которой так же нет реализации InsertRows, а она наверное есть в еще более дальнем предке и возвращает false, ничего больше не делая.

Из справки:
Цитировать
bool QAbstractItemModel::insertRows(int row, int count, const QModelIndex &parent = QModelIndex())

Note: The base class implementation of this function does nothing and returns false.
« Последнее редактирование: Сентябрь 06, 2016, 21:29 от break » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #10 : Сентябрь 06, 2016, 21:37 »

Цитировать
У меня класс унаследованный от  QSqlQueryModel.
А инсерт у меня в нем реализован свой и делается через sql зарос к базе.
Хорошо в этой вашей своей модели InsertRows виртуальный переопределен или свой какой нибудь метод типа "AddRow" для вставки новых записей?

Да типа AddRow.

Ну и что делать в итоге Непонимающий
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #11 : Сентябрь 06, 2016, 21:43 »

Реализовать в своей модели InsertRows причем через этот собственный AddRow  и все заработает ))) Если все правильно делать AddRow должен быть приватным, а все внешние вызовы вставки строки как раз и должны быть через InsertRows ( и InsertRow, который через него реализован ).
« Последнее редактирование: Сентябрь 06, 2016, 21:46 от break » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #12 : Сентябрь 06, 2016, 21:52 »

Реализовать в своей модели InsertRows причем через этот собственный AddRow  и все заработает ))) Если все правильно делать AddRow должен быть приватным, а все внешние вызовы вставки строки как раз и должны быть через InsertRows ( и InsertRow, который через него реализован ).

Так мне надо чтобы вставка строк была реализована без обращения к базе.
Чтобы я мог добавить их, отредактировать, а затем если все ок, то сделать комит и
добавить их тем самым в базу.

А по поводу insertRow.
 У меня класс модели унаследованный от QAbstractTableModel что-то тоже не работал.
Тоже false выдавал. Наверное я просто туплю. Обеспокоенный

Если сначала писать beginInsertRow() добавлять в список данных элемент  и endInsertRow() то тогда добавляется и норм. Но меня такой вариант не устраивает. Или я в чём-то заблуждаюсь. Непонимающий
« Последнее редактирование: Сентябрь 06, 2016, 22:02 от demaker » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #13 : Сентябрь 06, 2016, 22:22 »

Реализовать в своей модели InsertRows причем через этот собственный AddRow  и все заработает ))) Если все правильно делать AddRow должен быть приватным, а все внешние вызовы вставки строки как раз и должны быть через InsertRows ( и InsertRow, который через него реализован ).

Так мне надо чтобы вставка строк была реализована без обращения к базе.
Чтобы я мог добавить их, отредактировать, а затем если все ок, то сделать комит и
добавить их тем самым в базу.

Если модель унаследована от QSqlTableModel или ее наследников - можно использовать enum QSqlTableModel::EditStrategy - а именно вам в своей модели прийдется завести кеш и для значения этого энума OnManualSubmit - заносить данные лишь в кеш, а не в БД. Кейс по кешу будет именно в методе InsertRows, где и будет выбрано занести в БД сразу через AddRow или Занести только в кеш до вызова SubmitAll - когда весь несохраненный кеш заносить в БД - опять же через AddRow.

Этот убогий механизм есть в QtSql в связи с тем, что нет возможности прямой работы с транзакциями БД, точнее она есть в очень ограниченном виде. В идеальном варианте надо на уровне сервера БД все это делать, то есть проводить запросы, менять данные и т.д. в контексте текущей незавершенной транзакции, которая потом либо коммит, либо роллбак. Если Вы используете QSqlDatabase - то там есть метод transaction, который стартует транзакцию, и все созданные после этого QSqlQuery работают уже в ее контексте. Соответственно можно вызвать commit и rollback.

Цитировать
А по поводу insertRow.
 У меня класс модели унаследованный от QAbstractTableModel что-то тоже не работал.
Тоже false выдавал. Наверное я просто туплю. Обеспокоенный
Это понятно надо переопределять поведение InsertRows, чтобы оно что-то делало и не выдавало false.

Цитировать
Если сначала писать beginInsertRow() добавлять в список данных элемент  и endInsertRow() то тогда добавляется и норм. Но меня такой вариант не устраивает. Или я в чём-то заблуждаюсь. Непонимающий
beginInsertRows  и EndInsertRows вообще нужны в большей степени для блокировки и обновления вьюва. Чтобы он среагировал на то, что в модели появилась новая строка.

Вам надо определиться что именно Вы хотите - мое мнение, что при использовании моделей Qt в качестве базовых для своих моделей наследование виртуальной функции InsertRows обязательно, если модель редактируемая.
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #14 : Сентябрь 06, 2016, 22:41 »

Я кстати ошибся в QSqlTableModel InsertRows реализован и политика вставки там тоже работать должна. То есть в вашем случае как раз подойдет OnManualSubmit  если модель унаследована от QSqlTableModel. Ну или подобный механизм в своей модели реализовавыть. Или использовать транзакции.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.122 секунд. Запросов: 23.