crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

mva
  опции профиля:
сообщение 19.6.2009, 21:37
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 104
Регистрация: 15.3.2009
Из: Киров
Пользователь №: 615

Спасибо сказали: 3 раз(а)




Репутация:   0  


Доброго времени суток всем!

Работаю с моделью QSqlTableModel/QTableView.

EditStrategy == OnFieldChange.

Все работает хорошо, но есть одно НО...

Мне нужно, чтобы при изменении пользователем содержимого любой ячейки Grid эти изменения сразу же фиксировались на сервере без каких-либо задержек и нажатий дополнительных кнопок, просто при перемещении на другую ячейку.

Класс QSqlTableModel при изменении данных в одной строке (ячейке) отсылает изменения на сервер (у меня PostgreSQL), а затем ЗАГРУЖАЕТ ТАБЛИЦУ ЦЕЛИКОМ. С большой таблицей в локальной сети это будет работать сносно, а через Интернет - думаю, что очень медленно. Поэтому хочу изменить порядок обновления данных в QSqlTableModel - так, чтобы изменения на сервер отсылались, а последующая загрузка таблицы не происходила... Зачем загружать все данные, если пользователь изменил лишь одну ячейку?

Поясню на исходном коде класса QSqlTableModel.
bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    Q_D(QSqlTableModel);
    if (role != Qt::EditRole)
        return QSqlQueryModel::setData(index, value, role);

    if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
        return false;

    bool isOk = true;
    switch (d->strategy) {
    case OnFieldChange: {
        if (index.row() == d->insertIndex) {
            d->editBuffer.setValue(index.column(), value);
            return true;
        }
        d->clearEditBuffer();
        d->editBuffer.setValue(index.column(), value);
        isOk = updateRowInTable(index.row(), d->editBuffer);
    /*>>*/  if (isOk)            // хочу убрать этот код
    /*>>*/        select();
        break; }
    case OnRowChange:
        if (index.row() == d->insertIndex) {
            d->editBuffer.setValue(index.column(), value);
            return true;
        }
        if (d->editIndex != index.row()) {
            if (d->editIndex != -1)
                submit();
            d->clearEditBuffer();
        }
        d->editBuffer.setValue(index.column(), value);
        d->editIndex = index.row();
        emit dataChanged(index, index);
        break;
    case OnManualSubmit: {
        QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
        if (row.op == QSqlTableModelPrivate::None) {
            row.op = QSqlTableModelPrivate::Update;
            row.rec = d->rec;
            row.primaryValues = d->primaryValues(indexInQuery(index).row());
        }
        row.rec.setValue(index.column(), value);
        emit dataChanged(index, index);
        break; }
    }
    return isOk;
}


Пытаюсь создать наследника класса QSqlTableModel и переопределить в нем функцию setData:
bool MySqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
//    Q_D(QSqlTableModel);
    if (role != Qt::EditRole)
        return QSqlQueryModel::setData(index, value, role);

    if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
        return false;

    bool isOk = true;
    if (editStrategy == QSqlTableModel::OnFieldChange) {
        if (index.row() == d->insertIndex) {
            d->editBuffer.setValue(index.column(), value);
            return true;
        }
        d->clearEditBuffer();
        d->editBuffer.setValue(index.column(), value);
        isOk = updateRowInTable(index.row(), d->editBuffer);
    }
    else
        isOk = QSqlTableModel::setData(index, value, role);
    return isOk;
}

Проблема в том, что здесь используются какие-то недокументированные функции и переменные (например макрос Q_D и переменная d ), к которым я не знаю, как добраться. Код в таком виде не компилируется.

А может быть есть более простой путь?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
mva
  опции профиля:
сообщение 24.6.2009, 11:02
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 104
Регистрация: 15.3.2009
Из: Киров
Пользователь №: 615

Спасибо сказали: 3 раз(а)




Репутация:   0  


Решил я эту задачку... Пришлось изучать исходный код в части работы с базами данных. Как оказалось в этом плане Qt работает довольно примитивно. При использовании политики OnFieldChange результат изменений ячейки данных в Grid сначала отправляется на сервер, а затем для того, чтобы отобразить эти изменения, посылается запрос на загрузку всех данных... Это очень неэффективно... При использовании других политик происходит примерно то же самое, только с задержкой по времени. Для OnManualSubmit - изменения загружаются после команды submilAll. Но в этом случае изменения сохраняются в буфере и отображаются в виджете Grid. Этот момент я и использовал.

После множества экспериментов все свелось к простому дочернему классу:
class MySqlTableModel : public QSqlTableModel {
public:
    MySqlTableModel();
    bool setData(const QModelIndex &, const QVariant &, int);
};

MySqlTableModel::MySqlTableModel() : QSqlTableModel() {
    setEditStrategy(QSqlTableModel::OnManualSubmit);
}

bool MySqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
    bool lResult = false;
    lResult = QSqlTableModel::setData(index, value, role);
    if (lResult) {
        QSqlRecord rec = record(index.row());
        rec.setValue(index.column(), value);
        rec.setGenerated(index.column(), true);
        lResult = updateRowInTable(index.row(), rec);
    }
    return lResult;
}


При использовании этого класса вместо QSqlTableModel нет необходимости вызова submitAll для сохранении данных на сервере, хотя здесь и используется политика OnManualSubmit. Изменения сохраняются на сервере сразу, как только мы перемещаемся на другую ячейку, при этом фокус курсора не теряется (не изменяется). Это то, что мне и требовалось.


Чем-то этот вариант похож на предложение Литкевича Юрия.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


6 чел. читают эту тему (гостей: 6, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 18.2.2025, 11:06