Russian Qt Forum

Qt => Общие вопросы => Тема начата: demaker от Сентябрь 05, 2016, 19:13



Название: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 05, 2016, 19:13
Почему почему в QSortFilterProxyModel нельзя использовать insertRow()


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: PimenS от Сентябрь 05, 2016, 19:45
Потому что QSortFilterProxyModel не хранит данные, а работает с данными находящимися в установленной QAbstractItemModel *QAbstractProxyModel::sourceModel() const


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 05, 2016, 21:02
Логично.
Тогда как мне создать промежуточную модель, чтобы
можно в нее добавлять данные (несколько записей), а по нажатию кнопки
все скинуть в базу??? ???


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: ssoft от Сентябрь 06, 2016, 08:49
Наследуйтесь от QAbstractItemModel, помещайте внутрь другую модель  и реализуйте виртуальные методы с учетом вложенной модели. Должна получиться реализация похожая на QSortFilterProxyModel, только с вашей логикой добавления/редактирования/удаления элементов.


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: break от Сентябрь 06, 2016, 16:02
Почему почему в QSortFilterProxyModel нельзя использовать insertRow()
А почему нельзя? Вроде и можно и работает, специально проверил у себя.

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

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


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 06, 2016, 16:44
Почему почему в QSortFilterProxyModel нельзя использовать insertRow()
А почему нельзя? Вроде и можно и работает, специально проверил у себя.

Делаю так не работает
Код
C++ (Qt)
void DataBaseFilterModel::insertData()
{
   int lastRow = rowCount(QModelIndex());
   qDebug()<<lastRow;
   qDebug()<<insertRows(lastRow,1);//?????????????????????????????
}
 
В дебаге false


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 06, 2016, 18:02
Наследуйтесь от QAbstractItemModel, помещайте внутрь другую модель  и реализуйте виртуальные методы с учетом вложенной модели. Должна получиться реализация похожая на QSortFilterProxyModel, только с вашей логикой добавления/редактирования/удаления элементов.

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

Получается что мне нужно выгружать данные из в промежуточную модель в какой-то буффер
и добавлять туда при инсерте еще одну запись.
Так?   ???


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: break от Сентябрь 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 ?


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 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 зарос к базе.


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: break от Сентябрь 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.


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 06, 2016, 21:37
Цитировать
У меня класс унаследованный от  QSqlQueryModel.
А инсерт у меня в нем реализован свой и делается через sql зарос к базе.
Хорошо в этой вашей своей модели InsertRows виртуальный переопределен или свой какой нибудь метод типа "AddRow" для вставки новых записей?

Да типа AddRow.

Ну и что делать в итоге ???


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: break от Сентябрь 06, 2016, 21:43
Реализовать в своей модели InsertRows причем через этот собственный AddRow  и все заработает ))) Если все правильно делать AddRow должен быть приватным, а все внешние вызовы вставки строки как раз и должны быть через InsertRows ( и InsertRow, который через него реализован ).


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: demaker от Сентябрь 06, 2016, 21:52
Реализовать в своей модели InsertRows причем через этот собственный AddRow  и все заработает ))) Если все правильно делать AddRow должен быть приватным, а все внешние вызовы вставки строки как раз и должны быть через InsertRows ( и InsertRow, который через него реализован ).

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

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

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


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: break от Сентябрь 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 обязательно, если модель редактируемая.


Название: Re: QSortFilterProxyModel и insertRow
Отправлено: break от Сентябрь 06, 2016, 22:41
Я кстати ошибся в QSqlTableModel InsertRows реализован и политика вставки там тоже работать должна. То есть в вашем случае как раз подойдет OnManualSubmit  если модель унаследована от QSqlTableModel. Ну или подобный механизм в своей модели реализовавыть. Или использовать транзакции.