Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Flakes от Декабрь 30, 2008, 12:41



Название: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Декабрь 30, 2008, 12:41
Всем привет.

Работаю с QTableView и QSqlTableModel::OnFieldChange. После срабатывания submit() сбрасывается selection на модели. Я сохраняю selection в переопределенном setData(). Проблема в том, что мне теперь нужно восстанвоить selection, но никак не могу поймать тот самый момент, когда submit() сделался и модель обновилась, а selection соотвественоо сбросился. Пытался ловить и layoutChanged() и dataChanged(), и даже пулял emit dataChanged() внутри setData(), че то полная фигня, никакой сигнал не отлавливается.

Прошу о помощи!


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Пантер от Декабрь 30, 2008, 17:38
connect(tableView->selectionModel(),SIGNAL(selectionChanged...............


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Декабрь 30, 2008, 21:08
А оно не зависнет в бесконечно цикле, когда я сделаю ручной setSelection()?


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Пантер от Декабрь 30, 2008, 21:21
А ты проверяй в слоте на пустоту селекта. ;)


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Декабрь 30, 2008, 21:25
Попробую, пасиба.


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Январь 20, 2009, 02:35
В прошлый раз не вышло, решил передохнуть, но сейчас все таки уже приперло.

Значит у меня все обстоит так, кидаю полный код на основе cachetable example, чтоб было ясней некуда:

Код:
CustomSqlModel.cpp

CustomSqlModel::CustomSqlModel(QTableView **parentTable, QObject *parent) : QSqlTableModel(parent){
tableView = *parentTable;
}

bool CustomSqlModel::setData(const QModelIndex & index, const QVariant & value, int role){
saveSelection();
return QSqlTableModel::setData(index,value, role);
}

void CustomSqlModel::saveSelection(){
savedIndexList =  tableView->selectionModel()->selection().indexes();
}

void CustomSqlModel::loadSelection(){
// добавить немного волшебства тут
QItemSelection selection;
foreach (QModelIndex index, savedIndexList){
selection.select(index, index);
}
tableView->selectionModel()->select(selection, QItemSelectionModel::Select);
}

Код:
CustomSqlModel.h

class CustomSqlModel : public QSqlTableModel{
public:
CustomSqlModel(QTableView **parentTable, QObject *parent = 0);
QTableView *tableView;
QModelIndexList savedIndexList;
void saveSelection();
bool setData (const QModelIndex & index, const QVariant & value, int role);
void loadSelection();
};

Код:
TableEditor.cpp

TableEditor::TableEditor(){
QTableView *view = new QTableView;
model = new CustomSqlModel(&view, this);
...
connect(revertSelectionButton, SIGNAL(clicked()), this, SLOT(revertSelection()));
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(revertSelection()));
...
}

void TableEditor::revertSelection(){
model->loadSelection();
}

Код:
TableEditor.h
...
private slots:
void revertSelection();
private:
QPushButton *revertSelectionButton;
...

Как я и предполагал, после setData() оно начинает стучаться в loadSelection() и начинаются зацикливания. Делал проверки на что угодно, пытался делать с флагами, на пустоту селекта  - нет смысла, ибо после setData() селект еще пуст. К тому же selectionChanged() сработает как минимум столько раз, сколько элементов savedIndexList (чтоб не запутать кого, можно выбрать сколько угодно ячеек, редактироваться будет та, на которой установлен current), на деле он сработает куда больше раз, рекурсивно. Была идея делать каждый раз disconnect(), но че то повторный connect уже не срабатывает.
Вся прелесть в том, что если нажать revertSelectionButton - селект загрузиться как надо, автоматом же - нивкакую, начинает циклить и ничего не селектит ваще.

Взываю о помощи!


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Январь 24, 2009, 00:02
Посоветуйте куда копать???


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Январь 25, 2009, 19:23
Я перетрахался со всеми только возможными сигналами и слотами, будь то от QItemSelectionModel, QSqlTableModel или QTableView, к чему я только не пытался коннектить или переопределять: modelAboutToBeReset(), modelReset(), dataChanged(), submit(), reset(), currentChanged(). Ну как же мне эту суку отловить в момент когда данные засабмителись и модель обновилась?

Просто тишь да гладь. Дайте плиз кусочек рабочего кода.


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Dendy от Январь 25, 2009, 19:44
Чесно говоря, до конца не разбирался. Но вижу одну ошибку. Сохранять список индексов нужно в QList<QPersistentModelIndex>, а не в QModelIndexList.


Название: Re: QSqlTableModel :: dataChanged signal???
Отправлено: Flakes от Январь 25, 2009, 20:52
Ну может и так, только вот сохранением у меня нет проблем.

Еще обнаружил одну особенность, которая не поддается объяснению. Я законнектил selectionChanged и loadSelection, как в примере выше, только разбрасал чуть конкретней, loadSelection(const QItemSelection & selected, const QItemSelection & deselected). Вначале loadSelection поставил условие
Код:
if (!(selected.size() == 0 && deselected.size() != 0))
return;

Ну и вроде остальная часть loadSelection выполняется как раз когда мне надо. Особенность в том, что любые манипуляции с таблицей не срабатывают. Я думал, ну ладно, может selectionChanged срабатывает когда можель обновилась, а данные в таблице еще не успели отобразиться, и селект успевает сбрасываться, до того как я успею его увидеть.

Решил проверить с QTimer::singleShot(2000, tableView, SLOT(setFocus())), все равно не катит, однако катит, когда делается тот же QTimer::singleShot() через button какой-нить. Но это еще можно понять, что оно ушло в новый thread, а в первом треде данные уже изменились, и метод не валидный и срабатывает.

Уже крыша едет.