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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QSqlQueryModel + QSortFilterProxyModel + QTableView - обновление  (Прочитано 9992 раз)
root
Гость
« : Июнь 28, 2010, 07:06 »

Имею такую связку как в сабже, все это дело нужно только для отображения, фильтрации и сортировки данных из базы. Содержимое базы меняется разными клиентами. Требуется чтобы вьюха отображала актуальные данные.
Пробывал по разному - ничего не добился. Последний вариант вот такой:
наследуюсь от QSqlQueryModel, создаю публичный метод:
Код:
void CustQueryModel::updateModel() {    
    reset();
}
Наследуюсь от QSortFilterProxyModel, переопределяю методы flags, data, filterAcceptsRow - для своих нужд,
так же создаю публичный метод:
Код:
void FilterModel::updateMe() {
    reset();
}
Теперь метод который вызывается в программе, когда необходимо обновить данные:
(model - объект CustQueryModel(от QSqlQueryModel); filterModel - объект FilterModel(от QSortFilterModel); tableView - объект QTableView)
Код:
void ViewQuerys::updateTable() {
    if(model->query().exec()) {
        model->updateModel();
        filterModel->updateMe();
        tableView->reset();
    }
Думал, что такой вариант по любому заработает, однако ж нет..... В qt новичок, пишу первую программу,
как победить данную проблему не знаю, прошу помощи...
Записан
asvil
Гость
« Ответ #1 : Июнь 28, 2010, 07:29 »

QSqlQueryModel::reset() это сигнал. Сигнал ничего не делает кроме оповещения других участников программы о чем-либо.
Для того чтобы обновить QSqlQueryModel нужно повторно установить запрос в нее.
Записан
BRE
Гость
« Ответ #2 : Июнь 28, 2010, 08:14 »

QSqlQueryModel::reset() это сигнал.
Сигнал?
void QAbstractItemModel::reset ()   [protected]
Записан
asvil
Гость
« Ответ #3 : Июнь 28, 2010, 08:28 »

)Да, не прав. modelReset() - это сигнал. А reset() его впоследствии генерирует.
Так или иначе reset() не способствует обновлению Sql модели.
Записан
root
Гость
« Ответ #4 : Июнь 29, 2010, 06:37 »

Для того чтобы обновить QSqlQueryModel нужно повторно установить запрос в нее.

устанавливал - не помогло..... к тому же
Код:
model->query().exec()
не будет ли иметь тот же эффект?

Как же быть-то? самостоятельно решить проблему не получается.... Мож кто подскажет куда рыть? Может ли переопределение методов flags, data, filterAcceptsRow влиять на обновление модели?
Записан
asvil
Гость
« Ответ #5 : Июнь 29, 2010, 06:58 »

Так: QSqlQueryModel::setQuery(QSqlQueryModel::query())?
Возможно лучше так QSqlQueryModel::setQuery(QSqlQueryModel::query().lastQuery(), QSqlQueryModel::query().database())
Записан
root
Гость
« Ответ #6 : Июнь 29, 2010, 08:16 »

Проблему решил.
Сработал следущий способ:

1. Для QSqlQueryModel, устанавливаю повторно запрос
2. Выполняю его.
3. Вызываю свой метод в своей прокси модели, в котором вызывается reset()

Относительно кода в первом посте:

Код:
void ViewQueries::updateTable() {
    model.setQuery(/*#запрос#*/);
    if(model->query().exec()) {
        filterModel->updateMe();
    }
Метод updateMe() в наследнике QSortFilterProxyModel:

Код:
 void FilterModel::updateMe() {
    reset();
}

Скажу так же, что вызов layoutAboutToBeChanged(); layoutChanged() и т.д., вместо reset ничем не помогает. Если запрос не выполнить, то результата тоже не будет.... вот почему-то так.

Цитировать
Так: QSqlQueryModel::setQuery(QSqlQueryModel::query())?
да.
Цитировать
Возможно лучше так QSqlQueryModel::setQuery(QSqlQueryModel::query().lastQuery(), QSqlQueryModel::query().database())
возможно. Попробую. Спасибо за участие.
Записан
asvil
Гость
« Ответ #7 : Июнь 29, 2010, 08:30 »

QSortFilterProxyModel::dynamicSortFilter установлен в true?
Записан
root
Гость
« Ответ #8 : Июнь 29, 2010, 08:34 »

QSortFilterProxyModel::dynamicSortFilter установлен в true?
да

кстати, у мну нету метода database(), у объекта запрос. версия qt - 4.6.2
еще одно кстати, мое решение описанное выше, срабатывает почему-то только если весь алгоритм выполнить дважды.... теперь ломаю голову, почему так...  Непонимающий
« Последнее редактирование: Июнь 29, 2010, 08:44 от root » Записан
asvil
Гость
« Ответ #9 : Июнь 29, 2010, 08:45 »

if(model->query().exec()) {
// Здесь нужно сделать так чтобы прокси модель узнала, что model изменилась
// Для этого нужно сделать QSqlQueryModel::reset(), но он protected
        filterModel->updateMe();
    }

Значит наверно нужно сделать метод
QSqlQueryModel::refresh()
{
  query().exec();
  reset();
}

А вообще сама QSqlTableModel обновляет себя так:
Код:
QString query = selectStatement();
    if (query.isEmpty())
        return false;

    revertAll();
// Создает новый объект запроса
    QSqlQuery qu(query, d->db);
// Устанавливает данный запрос в QSqlQueryModel
    setQuery(qu);

    if (!qu.isActive() || lastError().isValid()) {
        // something went wrong - revert to non-select state
        d->initRecordAndPrimaryIndex();
        return false;
    }
    return true;
« Последнее редактирование: Июнь 29, 2010, 08:59 от Filonenko.Mikhail » Записан
asvil
Гость
« Ответ #10 : Июнь 29, 2010, 08:48 »

Цитировать
кстати, у мну нету метода database(), у объекта запрос. версия qt - 4.6.2
Это я навскидку про database писал.
Записан
root
Гость
« Ответ #11 : Июнь 29, 2010, 09:01 »

отнаследовался опять QSqlQueryModel, добавил метод
Код:
QSqlQueryModel::refresh()
{
  query().exec();
  reset();
}

результат тот же, как и в первом моем решении... обновляется только после повторения алгоритма 2 раза.....
Записан
root
Гость
« Ответ #12 : Июнь 30, 2010, 05:43 »

Решил проблему с необходимостью повтора алгоритма 2 раза. Но возникла новая  Улыбающийся
Значит новый алгоритм следующий:
1. Выполняем запрос  
2. Устанавливаем активный запрос в модель
3. ресетим проксю

То есть переписываем так:
(query - объект QSqlQuery, model - объект QSqlQueryModel, filterModel - объект наследника QSortFilterProxyModel)
Код:
void ViewQueries::updateTable() {
    query.exec();
    model.setQuery(*query);
    filterModel->refresh();
}

Метод refresh в своей проксе:
Код:
void FilterModel::refresh() {
    reset();
}

А новая пробема в следующем: Мой запрос выберает данные из нескольких таблиц, но не все возращаемые им поля надо отображать во вьюхе, поэтому некоторые столбцы во вьюхе у меня скрываются. Так вот, если результат запроса меняется в сторону увеличения (т.е. добавились новые строки), то после обновления вьюха отображает все корректно, с первого раза. А если результат запроса меньше, то после обновления количество строк вьюха отображает верно, но только почему то отображаются все поля запроса, даже те которые я скрывал во вьюхе. Приходится после обновления фиксить настройки отображения столбцов во вьюхе.....
« Последнее редактирование: Июль 01, 2010, 07:21 от root » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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