Название: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 23, 2012, 11:22 Странная несколько проблема. Таких же вопросов в инене видел много - но ответа на них нет. Может тут подскажут.
Есть наследник от QSqlQueryModel. Работает с движком SQLite. Необходимо редактировать данные - это я решил так Код
и необходимо вставить строку. В документации написано, что для этого нужно переопределить виртуальную ф-цию insertRows. А вот как ее переопределить для QSqlTableModel - не понятно. Пытался типа так Код
Не работает. Для других абстрактных моделях примеров много, а вот конкретно для этого ничего найти не смог. Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 23, 2012, 14:38 Цитировать Есть наследник от QSqlQueryModel. дык все-таки наследник от кого? QSqlQueryModel или QSqlTableModel? это принципиально.......... А вот как ее переопределить для QSqlTableModel - не понятно. Пытался типа так Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 23, 2012, 15:19 Наследник от QSqlTableModel - то, что принципиально понимаю. У наследников QSqlTableModel , как я понимаю, данные в памяти кешируются. И как я понимаю, данные отдельно ручками нужно вносить в базу на диске и в данные в самой модели.
Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 23, 2012, 16:03 Тогда setData и InsertRows Вам НЕ нужно переопределять.....
читаем справку по QSqlTableModel обращаем особое внимание на InsertRecord, setEditStrategy, revert, revertAll, submit, submitAll метод setData, у Вас в корне неправильный, оригинальный и так сделает соответствующий update для таблицы, правильнее переопределить метод flags Код:
Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 23, 2012, 16:26 Да я уже взад и вперед справку перечитал.
да есть у меня и Код
и Код
убрал свои методы setData и insertRows. Добавляю строку Код
в таблицу запись добавилась, но в вертикальном хедер около записи - * Вышли из программы - зашли снова - записи нет. И если редактируем - тоже изменения в базу на диск не вносятся. Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 23, 2012, 16:37 Код
Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 23, 2012, 16:46 Никаких сообщений....
Фантазии и меня закончились :) Перепробовал все варианты, что нашел. Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 23, 2012, 16:55 Пардон, вот так:
Код
Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 23, 2012, 17:01 О!
Спасибо большое! Хоть ошибку выдало - "near "(": syntax error Unable to execute statement" Пока правда непонятна что за скобка. Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 23, 2012, 17:10 Код
Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 24, 2012, 08:13 Вот что выдало (что собственно и должно было выдать)
"SELECT * FROM testtable ORDER BY DateIns ASC, TimeQIns ASC" Пока подозрение только одно - я заполняю QSqlTableModel при помощи такого запроса: - это в ф-ции openModel моей модели: Код т.е. не средствами QSqlTableModel, а прямым запросом. Может дело в этом? Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 24, 2012, 09:26 Спасибо большое за указание, где ошибки смотреть!
Разобрался, почему были ошибки. 1. Я сначала создавал QSqlTableModel - а уж потом подсоединялся к базе. Но это чисто моя ошибка - пока экспериментировал с программой, не заметил как это произошло. 2. Я считывал данные qobject_cast<QSqlQueryModel*>(this)->setQuery(queryStr); - данные считываются, но вот setTable все равно нужно задавать. Вот по этому у меня и не добавлялась запись. Однако появились другие проблемы: 1. При добавлении записи в таблицу, вся таблица перечитывается с диска, что долго. Есть возможность это как то обойти? 2. При выполнении операции Код
как сказать QTableView (да и всем другим компонентам) отключить вывод отображение данных из модели (наналог в Дельфи TTable.EnableControls/DisableControls)? Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 24, 2012, 11:32 Цитировать 2. Я считывал данные qobject_cast<QSqlQueryModel*>(this)->setQuery(queryStr); - данные считываются, но вот setTable все равно нужно задавать. Вот по этому у меня и не добавлялась запись. А вот так делать не надо! если вы хотите получить в итоге запрос типа: SELECT * FROM testtable ORDER BY DateIns ASC, TimeQIns ASC нужно перекрыть метод orderByClause()..., а для задания условий запроса - setFilter(); нельзя использовать внутренний query на прямую! через него QSqlTableModel читает и изменяет информацию, и соответственно текст sql-пердолжения в каждый момент разный в зависимости от операции!!! setTable("testtable"); // вытаскивает всю нужную информацию из системных таблиц (например название полей их тип и т.д.) select(); // выполнить запрос "select * from testtable" , QSqlTableModel формирует его динамически! Цитировать Однако появились другие проблемы: 1. При добавлении записи в таблицу, вся таблица перечитывается с диска, что долго. Есть возможность это как то обойти? 2. При выполнении операции 1. Может быть следствием вышесказанного, во всяком случае это в Вашем коде, QSqlTableModel - при вставке новой записи сама ничего не пересчитывает.... 2. tableView->blockSignals(true); Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 24, 2012, 16:31 Посмотрел исходники, поразберался.
Получается все немного не так: Метод orderByClause() нельзя перекрыть - он virtual protected. Да это и не надо. В принципе вполне пойдет и qobject_cast<QSqlQueryModel*>(this)->setQuery(queryStr); только перед этим нужно сделать setTable - чтоб поля таблицы определились. Ну вообще сортировка и выборка работают правильно - в интернете вроде как и советуют если нужна сложная сортировка напрямую setQuery вызывать. Тут вот сейчас вопрос про вставку: в таблице есть 10 тыс записей. При добавлении новой записи после submitAll происходит полное считывание записей с базы. Естественно медленно. Это так и должно быть? Специально для пробы все делаю по документации - открываю через select(). Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 24, 2012, 16:49 Цитировать Метод orderByClause() нельзя перекрыть - он virtual protected. Да ну, с каких это пор....вот кусок для PostgreSQL из реального проекта: Код
Цитировать При добавлении новой записи после submitAll происходит полное считывание записей с базы. Естественно медленно. Это так и должно быть? Да!Код
но можно перекрыть select()! Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 24, 2012, 21:42 Во первых - большое спасибо за ответы!
Во вторых - есть куча вопросов по PostgreSQL - но мучить вас я их не буду))) Давайте наверное опишу саму задачу, чтоб суть проблемы стала ясна: есть проект на Дельфи (мой проект). Проект очень большой, но большой не в плане работы с БД. Сейчас переделываю его на Qt , но 15 лет программирования на Дельфи сказываются - пытаюсь сделать как там))). Собственно все очень критичные части уже на Qt перенес. Осталась - работа с БД, которая в моем проекте достаточно простая. Хоть есть несколько критичных моментов. Но думал, что проблем не будет... Однако перечитал ВСЕ книги по Qt - все равно вопросы есть))) Это я к тому, что документацию я читаю. Теперь конктетика. 1. Есть критичная ситуация - время вставки записи в таблицу. При том что в таблице порядка 200 тыс записей (это максимум). Они отображаются в табличном виде. Вставленные новые записи нужно отображать в таблице. Естественно 200 тыс записей в память никто не считывает - в Дельфи в компоненте ADOQuery есть св-во - данные брать с сервера (постраничное отображение) или целиком скачивать. Тут я такое не нашел. 2. Продолжение предыдущего: в Qt считываются первые 450 записей. Почему первые? А если мне надо последние? 3. И все же мой код на редактирование: Код
Работает очень эффективно и быстро. Редактирование. В книге Бланшета и Саммерфильда в главе 13 (в книге 2007 года) предлагается нечто подобное. Вопрос собственно только в одном - как также быстро и эффективно вставлять строки))) Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: PavelVX от Июль 25, 2012, 05:38 Тоже присоединяюсь к теме, но маленько с другим вопросом: а как определить, что запись новая?
Ситуация: setEditStrategy(QSqlTableModel::OnManualSubmit); пользователь понавводил/поредактировал данные. Как мне отличить новая это строка или редактирование уже введенной? Причем isDirty() несколько кривовато работает. При смене строки в тейблвью смотрю состояние isDirty по предыдущему индексу. После редактирования, при сходе с редактируемой строки, isDirty == false!!!! Однако, если я потом вернусь на эту запись и опять с неё сойду, то isDirty == true :(. Я переопределил в своей модели setData(). По идее, при редактировании isDirty() после setData должен сбрасываться? Или мне что-то надо прописать в этом методе? Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 25, 2012, 08:08 Добавление к предыдущему вопросу: а есть ли опять де как в дельфийском TTable определить State: dsInsert, dsEdit - тоже пока это не нашел.
Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: PavelVX от Июль 25, 2012, 08:30 Добавление к предыдущему вопросу: а есть ли опять де как в дельфийском TTable определить State: dsInsert, dsEdit - тоже пока это не нашел. Что есть dsInsert, dsEdit? Метки состояния рекорда?Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 25, 2012, 11:20 Да.
Теперь по теме... Прочитал информацию по данному вопросу в инете - не утешительная информация. Qt не умеет читать из БД постранично. Вопрос: может кто озадачивался данной проблемой? Как допустим в табличном виде просмотреть 100 тыс записей, как это сделано в том же MS Access? В принципе проблему вставки записи/редактирования решил - отдельно вставляю в БД, отдельно в таблицу. Если делать submitAll() - происходит перечитывание всей таблицы, что неверно. Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 25, 2012, 11:59 2 Alex_C
ИМНО: у Вас в голове каша при использовании QSqlTableModel , по факту Вы пытаетесь из него сделать Редактируемую QSqlQueryModel..., в примерах Qt есть простенькая реализация такого класса, тока ее надо расширить и углубить Код
В Вашем случае: обновляет данные в кэше, и sumitAll() - непосредственно в базе QSqlTableModel::setData(index, value, role); ........ Еще раз обновляем те же данные сразу в базе..... return updateDataForColumn(getFieldNameByIndex(index.column()), index, value); Цитировать Вопрос собственно только в одном - как также быстро и эффективно вставлять строки))) Вставка как раз происходит быстро! А вот чтение обновленных данных - медленно.... можно например так - setQuery("select * testtable order by ...... limit кол_во_строк offset строка_номер" естественно "кол_во_строк" и "строка_номер" модель должна сама определять.... Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 25, 2012, 12:07 Наследуйте свою модель от QSqlQueryModel, setData у Вас уже есть,
только вот эту строку выкинуть: QSqlTableModel::setData(index, value, role); Вам осталось только InsertRows реализовать, ну и с постраничным выводом разобраться (см. пост выше) Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 25, 2012, 12:20 Цитировать Как допустим в табличном виде просмотреть 100 тыс записей Я бы ослеп на второй тысяче...... ??? Неужели все данные нужны сразу, и их можно проанализировать только последовательно листая экранами по ххх строк, 100К записей ??? Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: PavelVX от Июль 26, 2012, 05:01 А как определить, до сохранения в базу сабмитом, какие строки редактировались, а какие новые?
Как самому сбросить isDirty? Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: fte от Июль 26, 2012, 11:13 2 PavelVX
Цитировать Как самому сбросить isDirty? submit(),revert()Цитировать А как определить, до сохранения в базу сабмитом, какие строки редактировались, а какие новые? например использовать сигналы.....beforeInsert(),beforeUpdate(),beforeDelete() Название: Re: QSqlTableModel - добавить строку не получается. Отправлено: Alex_C от Июль 26, 2012, 11:34 Каши как раз в голове нет - просто пытался проблему решить что называется "малой кровью".
И в общем то решил, но решение самому не очень нравится. Правильное решение вот: можно например так - setQuery("select * testtable order by ...... limit кол_во_строк offset строка_номер" естественно "кол_во_строк" и "строка_номер" модель должна сама определять.... однако допустим на том же Access'е я не нашел такого варианта SELECT. Есть только SELECT TOP 100 ... но это считывает верхние 100 строк. Хотя учитывая что в Дельфи ADO умеет так делать - решение есть. Причем если понять как считывать группами из центра таблици, то реализовать подгруздку в таблицу динамически при скроллинге - не проблема. |