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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: QSqlQueryModel и нормальный refresh  (Прочитано 18586 раз)
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« : Сентябрь 22, 2014, 20:47 »

Как сделать нормальный, "обычный" refresh QTableVeiw, прицепленного к QSqlQueryModel?
Что имею ввиду под "нормальным":
1. собственно обновление изменившихся данных (новые/удаленные/изменившиеся строки) - это собственно сделано;
2. восстановление текущей позиции в QTableView - сделано, если текущая строка присутствует в обновленной модели;
3. если текущая строка в обновленной модели отсутствует - позиционироваться на следующую, если следующих нет тоже, то - на предыдущую.
Например, были такие строки:
1
2
3
4
5 - эта текущая
6
7

После обновления остались строки:
1
3
6 - эта должна стать текущей
7

Пока ничего лучшего придумать не могу кроме как, до обновления сохранять ключи для всех строки модели, перечитывать её, и потом в обновленной искать нужный индекс. Но, как-то этот из пушки по воробьям. Кто-нибудь предложит что-нибудь более совершенное?
Записан
Bepec
Гость
« Ответ #1 : Сентябрь 23, 2014, 07:51 »

Запоминать номер строки? Если у вас нет удаления нескольких записей, то вполне можно по номеру строки ориентироваться.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #2 : Сентябрь 23, 2014, 19:26 »

С чего вы взяли, что нет удаления нескольких записей? Это самая обычная многопользовательская БД - пользователи творят, что хотят и добавляют сколько им вздумается и удаляют, соответственно. Так что вариант с номерам строки не проходит однозначно. Как-то же оно реализовано в том же delphi, например. Там никогда вообще не задумывался над этим - всё идеально работало "из коробки" на даже самой банальной связке из DataSource и Grid, не говоря уже о продвинутых комбинациях типа FIBPlus + DevExpress. Тут же, даже чтобы банально обновить изменившееся в БД значение приходится весь query переустанавливать. Лучше бы вместо своих qml свистоперделок нормальный DB MVC сделали, а не этот костыль. Накипело, блин.
Записан
Figaro
Гость
« Ответ #3 : Сентябрь 23, 2014, 19:54 »

Первичный ключ запоминайте...
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #4 : Сентябрь 23, 2014, 22:49 »

И что мне с этого ключа? Вы пример мой смотрели? Что делать если запись с этим ключом удалили?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Сентябрь 24, 2014, 07:18 »

Так что вариант с номерам строки не проходит однозначно.
Не понял почему. Если номера удаляемых/вставляемых строк известны - что мешает пересчитать номер после выполнения операции ?
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #6 : Сентябрь 24, 2014, 08:04 »

Если номера удаляемых/вставляемых строк известны - что мешает пересчитать номер после выполнения операции ?
Дак откуда мне они известны? Да и что такое "номер строки"? Приложения работают на разных компах, пользователи сортируют таблицы как угодно. Строка номер 2 у одного пользователя может означать что угодно у другого!
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Сентябрь 24, 2014, 08:17 »

угодно. Строка номер 2 у одного пользователя может означать что угодно у другого!
Нужно уметь определять номер записи по уникальному id и id по номеру записи.
Перед рефрешем - определяете по номеру выбранной строки id записи, делаете рефрш, а после - находите по этому id номер строки.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #8 : Сентябрь 24, 2014, 08:31 »

Ну опять - посмотрите пример из первого поста. Перед рефреш у меня id текущей записи = 5, текущий № строки = 5. После рефреша получаю набор записей, в котором нет id=5 (кстати как именно мне это определить? на клиенте делать model->match() или на сервере в рамках транзакции исполнять ХП, которая перебирает записи в поиске номера строки?). И вот когда нет у меня после рефреш записи с запомненным id = 5 как мне встать на ту строку, которую я ожидаю увидеть (а именно № 4)?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #9 : Сентябрь 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.
Записан
OKTA
Гость
« Ответ #10 : Сентябрь 24, 2014, 11:05 »

Что-то я понять не могу, в чем проблема сделать запрос, который будет искать запись с нужным id, а если такой записи нет, то брать следующую по возрастанию или предыдущую при отсутствии записей с большим id??
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #11 : Сентябрь 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!!!
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Сентябрь 24, 2014, 13:39 »

А если у меня запрос возвращает не 20, а 2000 записей?
Список из 2000 64-битных id это 128Кб памяти. Улыбающийся

Кто-то (что-то) это же делает в других фреймворках!
Да как-то так и делают, только спрятано это под капотом.

Почему в Qt это всё должен делать я сам? Требую метод refresh на уровне QTableView!!!
Можно требовать или сделать один раз свою модель для работы с БД. Улыбающийся
« Последнее редактирование: Сентябрь 24, 2014, 13:43 от Old » Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #13 : Сентябрь 24, 2014, 17:08 »

Список из 2000 64-битных id это 128Кб памяти. Улыбающийся
Дело то не в объемах памяти. А в том, что мне придется обновленную модель прогонять (кстати, так и никто и не предложил как это делать "правильно") достаточно большое количество раз на предмет поиска в ней "наиболее меня устраивающего" (в смысле "ближайшего") к искомому id. А если в модели присутствуют блобы? Боюсь тогда fetch для всех её записей в рамках исполнения model->match() может "несколько затянуться". Ну а если этих записей вдруг станет 20000?

Можно требовать или сделать один раз свою модель для работы с БД. Улыбающийся
Можно и сделать. Но так можно и до собственной ОС докатиться. Хочется решать прикладные задачи, а не реализовывать такие свои модели, тем более что была надежда на то, что кто-то это сделает за (и лучше) меня.
« Последнее редактирование: Сентябрь 24, 2014, 21:56 от xokc » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Сентябрь 25, 2014, 10:30 »

Допустим это QList<int> oldKeys с ключами записей.
Напрашивается аналогичный newKeys считываемый после обновления, а дальше сравнение 2 массивов. И лучше напр QMap. После восстановления selection oldLКeys замещается на newKeys. Если модель обновляется извне - ничего лучшего не видно. В общем случае нет "ID записи", поэтому рассчитывать на сервис не приходится.

Но это же трындец! А если у меня запрос возвращает не 20, а 2000 записей? Это же банальный обычный refresh!!! Кто-то (что-то) это же делает в других фреймворках! Почему в Qt это всё должен делать я сам? Требую метод refresh на уровне QTableView!!!
Вот это и есть обратная сторона Qt Улыбающийся Что-то сделать руками - уже западло. В конце-концов остаются "ручки", и это плохо. Считайте что Вы получили "заряд бодрости"  Улыбающийся
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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