Название: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 22, 2014, 20:47 Как сделать нормальный, "обычный" refresh QTableVeiw, прицепленного к QSqlQueryModel?
Что имею ввиду под "нормальным": 1. собственно обновление изменившихся данных (новые/удаленные/изменившиеся строки) - это собственно сделано; 2. восстановление текущей позиции в QTableView - сделано, если текущая строка присутствует в обновленной модели; 3. если текущая строка в обновленной модели отсутствует - позиционироваться на следующую, если следующих нет тоже, то - на предыдущую. Например, были такие строки: 1 2 3 4 5 - эта текущая 6 7 После обновления остались строки: 1 3 6 - эта должна стать текущей 7 Пока ничего лучшего придумать не могу кроме как, до обновления сохранять ключи для всех строки модели, перечитывать её, и потом в обновленной искать нужный индекс. Но, как-то этот из пушки по воробьям. Кто-нибудь предложит что-нибудь более совершенное? Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Bepec от Сентябрь 23, 2014, 07:51 Запоминать номер строки? Если у вас нет удаления нескольких записей, то вполне можно по номеру строки ориентироваться.
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 23, 2014, 19:26 С чего вы взяли, что нет удаления нескольких записей? Это самая обычная многопользовательская БД - пользователи творят, что хотят и добавляют сколько им вздумается и удаляют, соответственно. Так что вариант с номерам строки не проходит однозначно. Как-то же оно реализовано в том же delphi, например. Там никогда вообще не задумывался над этим - всё идеально работало "из коробки" на даже самой банальной связке из DataSource и Grid, не говоря уже о продвинутых комбинациях типа FIBPlus + DevExpress. Тут же, даже чтобы банально обновить изменившееся в БД значение приходится весь query переустанавливать. Лучше бы вместо своих qml свистоперделок нормальный DB MVC сделали, а не этот костыль. Накипело, блин.
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Figaro от Сентябрь 23, 2014, 19:54 Первичный ключ запоминайте...
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 23, 2014, 22:49 И что мне с этого ключа? Вы пример мой смотрели? Что делать если запись с этим ключом удалили?
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Igors от Сентябрь 24, 2014, 07:18 Так что вариант с номерам строки не проходит однозначно. Не понял почему. Если номера удаляемых/вставляемых строк известны - что мешает пересчитать номер после выполнения операции ?Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 24, 2014, 08:04 Если номера удаляемых/вставляемых строк известны - что мешает пересчитать номер после выполнения операции ? Дак откуда мне они известны? Да и что такое "номер строки"? Приложения работают на разных компах, пользователи сортируют таблицы как угодно. Строка номер 2 у одного пользователя может означать что угодно у другого! Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 24, 2014, 08:17 угодно. Строка номер 2 у одного пользователя может означать что угодно у другого! Нужно уметь определять номер записи по уникальному id и id по номеру записи.Перед рефрешем - определяете по номеру выбранной строки id записи, делаете рефрш, а после - находите по этому id номер строки. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 24, 2014, 08:31 Ну опять - посмотрите пример из первого поста. Перед рефреш у меня id текущей записи = 5, текущий № строки = 5. После рефреша получаю набор записей, в котором нет id=5 (кстати как именно мне это определить? на клиенте делать model->match() или на сервере в рамках транзакции исполнять ХП, которая перебирает записи в поиске номера строки?). И вот когда нет у меня после рефреш записи с запомненным id = 5 как мне встать на ту строку, которую я ожидаю увидеть (а именно № 4)?
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 24, 2014, 10:53 Ну опять - посмотрите пример из первого поста. А для таких манипуляций, вам придется хранить табличку соответствий row - id до рефреша.До: 1 - 62 2 - 63 3 - 91 4 - 43 5 - 12 - текущая 6 - 23 7 - 24 После: 1 - 62 2 - 91 3 - 23 4 - 24 Мы знаем, что до рефреша текущей была строка с id = 12, пытаемся найти такую запись в выборке после, такой записи нет. Лезем в таблицу "До" и смотрим id следующей записи id = 23 - пытаемся найти ее в результирующей выборке - нашли, это row = 3. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: OKTA от Сентябрь 24, 2014, 11:05 Что-то я понять не могу, в чем проблема сделать запрос, который будет искать запись с нужным id, а если такой записи нет, то брать следующую по возрастанию или предыдущую при отсутствии записей с большим id??
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 24, 2014, 13:25 Мы знаем, что до рефреша текущей была строка с id = 12, пытаемся найти такую запись в выборке после, такой записи нет. Лезем в таблицу "До" и смотрим id следующей записи id = 23 - пытаемся найти ее в результирующей выборке - нашли, это row = 3. В чем проблема сделать запрос, который будет искать запись с нужным id, а если такой записи нет, то брать следующую по возрастанию или предыдущую при отсутствии записей с большим id?? Этот-то вариант понятен его я и имел ввиду когда говорил в первом посте про "до обновления сохранять ключи для всех строки модели, перечитывать её, и потом в обновленной искать нужный индекс".Но при этом мне нужно: 1. Хранить результат выборки до обновления с учетом всех манипуляций, которые умудрился над запросом совершит пользователь (сортировки и фильтрации на клиенте). Допустим это QList<int> oldKeys с ключами записей. 2. После обновления проверять в ней наличие (и снова - как проверять: через model->match()?) ключа текущей записи. Если её там нет - крутить цикл по oldKeys вниз от текущей строки до обнаружения в новой модели очередного ключа. Если такой не найдется, то делать тоже самое вверх по oldKeys. Если опять ничего не найдется - то позиционироваться на первой записи. Но это же трындец! А если у меня запрос возвращает не 20, а 2000 записей? Это же банальный обычный refresh!!! Кто-то (что-то) это же делает в других фреймворках! Почему в Qt это всё должен делать я сам? Требую метод refresh на уровне QTableView!!! Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 24, 2014, 13:39 А если у меня запрос возвращает не 20, а 2000 записей? Список из 2000 64-битных id это 128Кб памяти. :)Кто-то (что-то) это же делает в других фреймворках! Да как-то так и делают, только спрятано это под капотом.Почему в Qt это всё должен делать я сам? Требую метод refresh на уровне QTableView!!! Можно требовать или сделать один раз свою модель для работы с БД. :)Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 24, 2014, 17:08 Список из 2000 64-битных id это 128Кб памяти. :) Дело то не в объемах памяти. А в том, что мне придется обновленную модель прогонять (кстати, так и никто и не предложил как это делать "правильно") достаточно большое количество раз на предмет поиска в ней "наиболее меня устраивающего" (в смысле "ближайшего") к искомому id. А если в модели присутствуют блобы? Боюсь тогда fetch для всех её записей в рамках исполнения model->match() может "несколько затянуться". Ну а если этих записей вдруг станет 20000?Можно требовать или сделать один раз свою модель для работы с БД. :) Можно и сделать. Но так можно и до собственной ОС докатиться. Хочется решать прикладные задачи, а не реализовывать такие свои модели, тем более что была надежда на то, что кто-то это сделает за (и лучше) меня.Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Igors от Сентябрь 25, 2014, 10:30 Допустим это QList<int> oldKeys с ключами записей. Напрашивается аналогичный newKeys считываемый после обновления, а дальше сравнение 2 массивов. И лучше напр QMap. После восстановления selection oldLКeys замещается на newKeys. Если модель обновляется извне - ничего лучшего не видно. В общем случае нет "ID записи", поэтому рассчитывать на сервис не приходится.Но это же трындец! А если у меня запрос возвращает не 20, а 2000 записей? Это же банальный обычный refresh!!! Кто-то (что-то) это же делает в других фреймворках! Почему в Qt это всё должен делать я сам? Требую метод refresh на уровне QTableView!!! Вот это и есть обратная сторона Qt :) Что-то сделать руками - уже западло. В конце-концов остаются "ручки", и это плохо. Считайте что Вы получили "заряд бодрости" :)Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 10:47 1. собственно обновление изменившихся данных (новые/удаленные/изменившиеся строки) - это собственно сделано; Есть подозрение, что если нормально обновлять модель (испускать соответствующие сигналы), то вью сама должна нормально позиционировать текущий элемент и вьюпорт.Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 25, 2014, 13:07 если нормально обновлять модель (испускать соответствующие сигналы), то вью сама должна нормально позиционировать текущий элемент и вьюпорт. И ещё раз: есть 2 разных компа с моими приложениями. На PC1 пользователь удалил запись, которая является в этот момент текущей во вью на PC2. Кто, кому и какой должен испустить сигнал, чтобы при обновлении вью на PC2 текущей стала "ожидаемая строка"?Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 25, 2014, 13:10 И ещё раз: есть 2 разных компа с моими приложениями. На PC1 пользователь удалил запись, которая является в этот момент текущей во вью на PC2. Кто, кому и какой должен испустить сигнал, чтобы при обновлении вью на PC2 текущей стала "ожидаемая строка"? У меня база посылает уведомление о изменении таблицы (добавление/изменение/удаление записи) и все модели на всех рабочих местах добавляют/перечитывают/удаляют нужную строку.База postgresql. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 13:18 И ещё раз: есть 2 разных компа с моими приложениями. На PC1 пользователь удалил запись, которая является в этот момент текущей во вью на PC2. Кто, кому и какой должен испустить сигнал, чтобы при обновлении вью на PC2 текущей стала "ожидаемая строка"? Каким образом обновляется модель на PC2?Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Hellraiser от Сентябрь 25, 2014, 13:25 У меня база посылает уведомление о изменении таблицы (добавление/изменение/удаление записи) и все модели на всех рабочих местах добавляют/перечитывают/удаляют нужную строку. Таковым механизмом обладают далеко не все СУБД. В таком случае - либо кнопка рефреша, либо костыль с таймером.База postgresql. У меня при выборе СУБД для проекта наличие механизма нотификации дало серьезное преимущество для Постгре. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 25, 2014, 13:26 Каким образом обновляется модель на PC2? По нажатию кнопки "Refresh".У меня база посылает уведомление о изменении таблицы. Уходим в сторону от изначального вопроса, который заключался не в этом, а в том, как "ожидаемо" спозиционироваться на строку после рефреша, если предыдущая текущая запись была удалена. Плюс мне такой подход с автоматическим обновлением по уведомлению об изменении не подойдет: изменения происходят слишком часто - в этом режиме работать с таблицей будет невозможно. Кстати, как узнаёте, что инициатором изменения была текущая модель, и, следовательно, специально обновляться не надо?Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 13:27 Таковым механизмом обладают далеко не все СУБД. В таком случае - либо кнопка рефреша, либо костыль с таймером. Мало того, ни каждая система и клиент может выдержать нагрузку используя такой механизм.Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 13:29 По нажатию кнопки "Refresh". Ну что за ответ ???Тебе хотят помочь, а ты кривляешься. Как-то даже не серьёзно. :( Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 25, 2014, 13:39 По нажатию кнопки "Refresh". Ну что за ответ ???Тебе хотят помочь, а ты кривляешься. Как-то даже не серьёзно. :( Код
Тебе хотят помочь От помощи не откажусь и буду благодарен - для того и вопрос задавал.Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 13:56 Получается, что модель при обновлении полностью чистится. Поэтому вью тоже сбрасывается.
Тут есть 2 решения, либо написать свою модель с нормальным рефрешем либо держать 2 QSqlQueryModel-и. Первая основная, а вторая временная для валидации первой. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 25, 2014, 13:59 Кстати, как узнаёте, что инициатором изменения была текущая модель, и, следовательно, специально обновляться не надо? У меня все действия с таблицей можно выполнять только через методы модели, поэтому внутримодельного флага достаточно.Я не использую Qt-модели для работы с базами, сразу написал свои со всякими "плюшками". Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 25, 2014, 14:02 Получается, что модель при обновлении полностью чистится. Поэтому вью тоже сбрасывается. Достаточно хранить список с уникальными id записей. Перед рефрешем заполняем его, после смотрим что изменилось.Тут есть 2 решения, либо написать свою модель с нормальным рефрешем либо держать 2 QSqlQueryModel-и. Первая основная, а вторая временная для валидации первой. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 14:07 Достаточно хранить список с уникальными id записей. Перед рефрешем заполняем его, после смотрим что изменилось. Да, так будет ещё оптимальнее.Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 25, 2014, 14:13 Спасибо за ответы, вижу, что простого решения нет - жаль. Ну и пользуясь случаем: у меня в модели есть "вычисляемое" поле, то есть то поле, которого нет в БД (значение из модели отдается через model::data()). Как мне при его изменении (не средствами View) наиболее правильно оповестить View о том, что надо бы это значение перерисовать без полного refresh (как сделано в примере editablemodel) модели?
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Сентябрь 25, 2014, 14:20 Код
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: Old от Сентябрь 25, 2014, 14:24 Как мне при его изменении (не средствами View) наиболее правильно оповестить View о том, что надо бы это значение перерисовать без полного refresh (как сделано в примере editablemodel) модели? Модель должна послать сигнал:void QAbstractItemModel::dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ()) [signal] Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Сентябрь 25, 2014, 16:25 Ок, благодарю. Буду пробовать.
Название: Re: QSqlQueryModel и нормальный refresh Отправлено: panAlexey от Сентябрь 30, 2014, 22:24 С чего вы взяли, что нет удаления нескольких записей? Это самая обычная многопользовательская БД - пользователи творят, что хотят и добавляют сколько им вздумается и удаляют, соответственно. а вот это не гуд. лучше не удалять, а помечать на удаление и чистить с контролем ссылочной целкости. Название: Re: QSqlQueryModel и нормальный refresh Отправлено: panAlexey от Сентябрь 30, 2014, 22:27 1. собственно обновление изменившихся данных (новые/удаленные/изменившиеся строки) - это собственно сделано; Есть подозрение, что если нормально обновлять модель (испускать соответствующие сигналы), то вью сама должна нормально позиционировать текущий элемент и вьюпорт.Название: Re: QSqlQueryModel и нормальный refresh Отправлено: xokc от Октябрь 01, 2014, 20:02 а вот это не гуд. лучше не удалять, а помечать на удаление и чистить с контролем ссылочной целкости. Чем же это "не гуд"? Во-первых пометка к удалению вместо собственно удаления ну никак не решит мою проблему, а во-вторых пусть уж хоть этим занимается не приложение, а СУБД (с чем, общем он вполне успешно справляется).Название: Re: QSqlQueryModel и нормальный refresh Отправлено: GreatSnake от Октябрь 02, 2014, 09:50 а вот это не гуд. лучше не удалять, а помечать на удаление и чистить с контролем ссылочной целкости. Во-первых пометка к удалению вместо собственно удаления ну никак не решит мою проблему |