crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> Выбор строки после редактирования, QSqlQueryModel + QSortFilterProxyModel + QTableView
512es
  опции профиля:
сообщение 1.12.2009, 15:05
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 135
Регистрация: 31.10.2008
Пользователь №: 407

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




Репутация:   0  


Всем привет!

Много гуглил, искал решение, чего только не перепробовал. Но проблему так и не удалось решить:
На основе примера *\qt\examples\sql\querymodel\editablesqlmodel.cpp сделал редактируемую QSqlQueryModel, и прикрутил к ней QSortFilterProxyModel.
Вот кусок кода, по которому видно, что я уже перепробовал:
bool cliviewModel::setData(const QModelIndex &index, const QVariant &value, int  role)
{
     if (!index.column()) return false;
     QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
     int id = data(primaryKeyIndex,0).toInt();
//     clear();
     qDebug() << index.row() << sortingModell->mapFromSource(index).row();
     bool ok=0;
     QSqlQuery query;
     query.prepare("UPDATE clients SET " + colums.value(index.column()) + " = ? WHERE client_id = ?");
     query.addBindValue(value.toString());
     query.addBindValue(id);
     ok = query.exec();
     if (ok) {
         setQuery(lastQuery);
         while (canFetchMore()) fetchMore();
//         eatMouseEvent = 1;
   //      QMap<int, QVariant> itemData;
   //      itemData.insert(Qt::DisplayRole, value);
   //      QAbstractItemModel::setItemData(index,itemData);
   //      emit(dataChanged(index, index));
         emit signalGoToClientById(index);
//         qDebug() << setData(index, QString(tr("Исходящий")), Qt::DisplayRole);
     }
     return ok;
}


Задача: после редактирования ячейки обновить отображаемые данные в таблице и оставить выбранной ячейкой ту, которую мы редактировали.

Для этой цели вызываю сигнал emit signalGoToClientById(index), который соединён со слотом:
void CliView::slotGoToEdited(const QModelIndex &current)
{
    QModelIndex cur = modell->sortingModell->mapFromSource(current);
    scrollTo(cur,QAbstractItemView::EnsureVisible);
    setCurrentIndex(cur);
}


Оно работает, но если я выхожу из редактирования кликом мышки, то после того как выставить нужную ячейку, курсор переходит на ту строку, куда я кликнул.

Помогите люди добрые, наверняка вы уже сталкивались с этой же проблемой..

Сообщение отредактировал 512es - 1.12.2009, 15:07
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 1.12.2009, 15:49
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9666
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


Цитата(512es @ 1.12.2009, 18:05) *
после редактирования ячейки обновить отображаемые данные в таблице и оставить выбранной ячейкой ту, которую мы редактировали.
тут нужна оговорка, "если эта ячейка ещё существует" т.к. в ощем случае её мог удалить другой пользователь.

Модельные индексы непостоянны, т.е. они имеют свойство менять своё значение (показывать в другое место). Попробуй запоминать "постоянный модельный индекс" (QPersistentModelIndex) и по нему восстанавливать выделение
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
512es
  опции профиля:
сообщение 7.12.2009, 16:09
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 135
Регистрация: 31.10.2008
Пользователь №: 407

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




Репутация:   0  


Цитата(Litkevich Yuriy @ 1.12.2009, 15:49) *
Модельные индексы непостоянны, т.е. они имеют свойство менять своё значение (показывать в другое место). Попробуй запоминать "постоянный модельный индекс" (QPersistentModelIndex) и по нему восстанавливать выделение

QPersistentModelIndex не решил моей проблемы(


Если не пытаться переходить на изменившуюся ячейку, т.е.
// emit signalGoToClientById(index);
то курсор будет переходить туда, куда мы кликнули.
Но если прокрутить таблицу вниз, и попытаться изменить ячейку, после чего перейти кликом на другую, то курсор попадёт туда, где была бы эта строка, если бы мы были вначале списка.


Описание глюка:
Допустим, в таблице 10 строк. За раз видно на экране 5 строк.
1) При редактировании 3-ей строки и выхода из редактирования кликнув на 4-ую мы попадём на 4-ую (как вроде и должно быть)
Цитата
[зона видимости
1......
2......
3...... <- редактируем
4...... <- клик, выход из редактирования <- попадаем сюда
5......
зона видимости]
6......
7......
8......
9......
10....


2) А если мы прокрутили таблицу в конец (т.е. видим только 6-10 строки), редактируем 8-ую строку, и выходим из редактирования кликом на 9-ую, мы снова попадём на 4-ую строку!
Цитата
1......
2......
3......
4...... <- попадаем сюда!!!!
5......
[зона видимости
6......
7......
8...... <- редактируем, надо перейти сюда
9...... <- клик, выход из редактирования
10....
зона видимости]


А теперь, если я даже вызову сигнал перехода на нужную строку, после обновления данных:
3) Редактируем 8-у, клик по 9-ой, сигналом перескакиваю на 8-ю (как и должно быть), но потом всё равно курсор возвращается на 4-ую строку!

Я даже пробовал переходить на одну и ту же конкретную строку, например:
selectRow(900);

Всё равно попадаю туда, куда кликнул до обновления таблицы.

Хелп!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 7.12.2009, 17:19
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9666
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


Цитата(512es @ 7.12.2009, 19:09) *
selectRow(900);
это не переход на строку, а её выделение, для перехода нужно устанавливать текущую, ключевые слова: "set current"
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
512es
  опции профиля:
сообщение 9.12.2009, 17:26
Сообщение #5


Участник
**

Группа: Участник
Сообщений: 135
Регистрация: 31.10.2008
Пользователь №: 407

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




Репутация:   0  


Цитата(Litkevich Yuriy @ 7.12.2009, 17:19) *
Цитата(512es @ 7.12.2009, 19:09) *
selectRow(900);
это не переход на строку, а её выделение, для перехода нужно устанавливать текущую, ключевые слова: "set current"

setCurrentIndex(cur) ? Это в первом посте. Пробовал и так и так. У меня в таблице выделение по строкам идёт, поэтому для меня сейчас это синонимы.

Так и не решил проблему. Перепробовал уже, как мне кажется, все возможные методы.. Перегуглил весь инет. Неужели нельзя QSqlQueryModel заставить работать как полагается??

В QSqlTableModel была у меня такая же проблема, я её решил с помощью updateRowInTable() в setData().
Но, в QSqlQueryModel нету возможности изменять данные в таблице! По крайней мере я не нашёл..
Хотя есть одна идейка только.. Через data() менять текст отображения изменёных ячеек. А изменёные индексы и содержание хранить в массиве.. Вот только не знаю, на сколько это правильно..

Мужики, выручайте, проект горит! Подскажите, в какую сторону копать!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 9.12.2009, 17:35
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9666
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

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




Репутация:   94  


Цитата(512es @ 9.12.2009, 20:26) *
Неужели нельзя QSqlQueryModel заставить работать как полагается??
а эта модель здесь вообще не причём. За отображение информации отвечает представление, если вести речь о выделении, то SelectionModel этого представления.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
512es
  опции профиля:
сообщение 9.12.2009, 21:46
Сообщение #7


Участник
**

Группа: Участник
Сообщений: 135
Регистрация: 31.10.2008
Пользователь №: 407

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




Репутация:   0  


Litkevich Yuriy, за SelectionModel спасибо. Хоть мне и не нужно многостроковое выделение, зато с помощью QItemSelectionModel теперь могу выделять строку прямо из класса модели, без сигналов.

Вот только всё равно это не решило проблему.
QItemSelectionModel, setCurrentIndex() и selectRow() дают тот же результат (в моём случае).

Делаю вот так:
void MyQTableView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
    if (current.row() == previous.row()||current.row() == -1) return;
    qDebug() << "currentChanged" << current.row();
    QAbstractItemView::currentChanged(current, previous);
}


bool MyQSqlQueryModel::setData(const QModelIndex &index, const QVariant &value, int  role)
{
     if (!index.column()) return false;
     if (role != Qt::EditRole) return true;
     QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
     int id = data(primaryKeyIndex).toInt();
     bool ok=0;
     QSqlQuery query;
     query.prepare("UPDATE clients SET " + colums.value(index.column()) + " = ? WHERE client_id = ?");
     query.addBindValue(value.toString());
     query.addBindValue(id);
     ok = query.exec();
     if (ok) {
         qDebug() << "setData" << index.row();
         setQuery(lastQuery);
         while (canFetchMore()) fetchMore();
         selectionMode1->setCurrentIndex(QSqlQueryModel::index(800,0),QItemSelectionModel::Select);
     }
     return ok;
}


Получаем вот такой результат:
currentChanged 54               // двойной клик на строку 54
setData 54                                    // редактирование
currentChanged 800                      // выход из редактирования по клику на любой другой ячейке. перешли на строку 800
currentChanged 784                      // почему ???!! кажется сработал мой клик при выходе из редактирования.. как блокировать??                
currentChanged 843                      // двойной клик на строку 843
setData 843                                  // редактирование
currentChanged 800                      // выход из редактирования по клику на любой другой ячейке. перешли на строку 800
currentChanged 799                      // ну вот, опять! это число зависит от того, в какую область я щёлкнул..
currentChanged 853                      // ну, и т.д..
setData 853
currentChanged 800
currentChanged 786


Может через Block Signal? Вот только не знаю, какой.. И откуда он берётся..
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
512es
  опции профиля:
сообщение 9.12.2009, 23:11
Сообщение #8


Участник
**

Группа: Участник
Сообщений: 135
Регистрация: 31.10.2008
Пользователь №: 407

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




Репутация:   0  


Уф.. У меня получилось!!

Полторы недели мучений, а оказывается всё было так просто!!

Решение:
Нельзя обновлять модель в setData() через повторное setQuery! Обновлять нужно так: this->query().exec();


И никто мне не подсказал....
=(

Сообщение отредактировал 512es - 9.12.2009, 23:14
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 5.3.2021, 14:07