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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с удалением в QSqlTableModel  (Прочитано 7561 раз)
iamfomik
Гость
« : Сентябрь 09, 2008, 22:39 »

Всем привет.

Недавно перешёл на новую версию QT - 4.4.1 и начал разрабатывать программку, которая работает с MySQL. Так вот, пишу, значит,  всё как и обычно делаю и тут замечаю некоторые аномалии:
-во-первых, не могу изменить данные у QSqlTableModel методом setRecord с EditStrategy=OnManualSubmit. Всё делаю как обычно а мне в ответ сообщение "No fields to update." До этого проект крупненький разрабатывали, там я точно так же пользовался и всё работало(там была какая-то более старая версия библиотеки). Собрал тот же проект с новой версией QT и точно такая же ошибка. При этом добавление работает отлично. Помогло только откат до предыдущей версии.

-во-вторых, в программе никак не могу реализовать удаление из списка QListView. Ставлю у модели EditStrategy=OnManualSubmit, устанавливаю для QListView эту модель и описываю слот на удаление записи:
Код:
if(model->removeRow(ui.listView->currentIndex().row()))
{
ui.listView->setCurrentIndex(model->index(0,1));
}else
qCritical() << model->lastError().text();
и ни чего не происходит - removeRow возвращает true и всё. Далее, если сделать EditStrategy=OnRowChange то всё работает. Но мне такое не нужно, мне нужно чтобы потом по кнопке было либо submitAll либо revertAll. А больше всего меня поразило то, что эта же программа, откомпилированная в линуксе, всё нормально удаляет как я задумал.

Пробовал понять исходный код QSqlTableModel, но после минуты осмотра он мне показался правильным =)
Уж и не знаю как проблему исправить. Желающие прояснить ситуацию есть? =)
Записан
ритт
Гость
« Ответ #1 : Сентябрь 09, 2008, 23:27 »

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

под линуксом какая версия кутэ?
Записан
iamfomik
Гость
« Ответ #2 : Сентябрь 10, 2008, 14:12 »

под линуксом версия 4.4.0, сейчас под виндой тоже. Ещё тестировал на FreeBSD.
во вложении два примера и стуктура БД к ним.
первая программа просто изменяет запись. Вторая программа позволяет добавлять и удалять записи через QListView.

после некоторых экспериментов:
версия QT 4.4.1 FreeBSD
первая программа пишет "No Fields to update"
вторая программа делает так - removeRow возвращает true но из ListView строка не удаляется, а если нажать на SaveAll то строка удаляется.
версия QT 4.4.1 Windows
первая работает аналогично
вторая никак не хочет реагировать и удалять

версия QT 4.4.0 Windows
первая программа работает отлично.
вторая так же как и QT 4.4.1 FreeBSD

Мне просто хочется использовать версию 4.4.1, потому хотелось бы разобраться с первой проблемой. Кстати говоря, setRecord там нормально изменяет запись, и если к той модели ещё и QSqlTableView подключить то, если после изменения потыкать по ячейкам, видно что запись изменяется. Однако model->submitAll в любом случае вызывает ошибку - "No fields to update".
Впринципе вторая проблема не является проблемой, скорее корявостью. Может это я не так удаляю??? Мне нужно чтобы при нажатии на кнопку из списка удалялась строка, и только по нажатию на кнопку "saveAll" записи удалялись бы из БД.

Вариант с изменением EditStrategy на любую другую для меня не приемлем.
Записан
ритт
Гость
« Ответ #3 : Сентябрь 10, 2008, 20:08 »

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

вторая проблема - вовсе и не проблема. если бы у тебя был тэйблвью вместо листвью, сразу бы увидел, что строка при мануалсабмит только помечается на удаление, а удаляется непосредственно при сабмите. если не хочется наследоваться от модели, можно просто ловить её (модели) сигнал headerDataChanged для Qt::Vertical и сравнивать headerData для Qt::DisplayRole с QLatin1String("!") - так визуально строка помечается на удаление
Записан
iamfomik
Гость
« Ответ #4 : Сентябрь 10, 2008, 20:21 »

хммм.... а как бы мне по сигналу от модели void beforeDelete( int row ) скрыть элемент в листВью Непонимающий Или придётся наследовать? А если наследовать то как лучше сделать?
Записан
ритт
Гость
« Ответ #5 : Сентябрь 10, 2008, 20:50 »

сигнал beforeDelete высылается перед фактическим удалением строки - т.е. уже после submitAll
я так понял, что тебе это не подходит...

> ловить сигнал headerDataChanged для Qt::Vertical бла-бла-бла
самый простой способ реализовать данный перехват и не перегружать скл-модель - отнаследоваться от QSortFilterProxyModel, перегрузить filterAcceptsRow (проверять дату на равность QLatin1String("!")) и включить у прокси динамиксортфильтер
таким образом строка будет скрываться из вьюхи в тот же момент, когда нажали кнопку "удалить", а фактически удаляться из бд строка будет только после submitAll (кстати, reverAll автоматически сделает строку снова видимой)

по первой проблеме могу ещё предлложить отказаться от "ручного" перебора данных и довериться замечательному классу QDataWidgetMapper. позже я код всё-равно посмотрю, но на данный момент использование QDataWidgetMapper полностью закрыло бы проблему
Записан
iamfomik
Гость
« Ответ #6 : Сентябрь 11, 2008, 09:44 »

На счёт прокси модели - это выход.

А  QDataWidgetMapper'ы не всегда подходят. Во-первых проект уже написан, и делать глобальные изменения неуместно(я пока выбрал для него вариант откатить до старой версии QT). Во-вторых, не все поля таблицы можно связать через маппер, например иногда нужно что-то в ручную записать, то что не отображается, то что считается вручную. Хотя я бы конечно лучше использовал маппер(не понимаю почему я им не воспользовался =))
Как вариант решения проблемы с не полной универсальностью маппера - создать виртуальный виджет, он по интерфейсам будет подходить к мапперу, но он не будет рисоваться. Или есть другой способ? Или в QTуже есть подобие виртуального виджета?
Записан
ритт
Гость
« Ответ #7 : Сентябрь 11, 2008, 10:56 »

колеса ("виртуального виджета") изобретать не надо. датавиджетмапперу можно установить делегат - надеюсь, этим всё сказано и не нужно расжёвывать? Улыбающийся
если какие-то поля не нужно отображать, думаю, и редактировать их не нужно - просто не мапим их

даже в случае, если ты всё-равно не захочешь связываться с датавиджетмаппером, можно писать данные через setData, а не через setRecord...
Записан
iamfomik
Гость
« Ответ #8 : Сентябрь 11, 2008, 16:54 »

С виджет маппером наоборот - очень хочу с ним связываться. Использовать setData конечно можно, но гораздо больше кода будет...но это всё ладно...

Если какие-то поля не нужно отображать, то это не значит что их не нужно маппить.

Вот на счёт делегатов это ты точно сказал, я совсем и забыл про них. Не совсем представляю как написать делегат который будет кушать и виджеты и просто переменные, но думаю способ найду. Кстати и проблему с удалением я намерен решить тоже при помощи делегата - есть такой QStyledItemDelegate, отнаследуюсь от него и просто буду удалённые записи помечать или скрывать.

Спасибо за помощь, если проверишь ошибку под QT 4.5 отпишись потом, если не сложно.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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