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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Смущает beginInsertRows  (Прочитано 9717 раз)
Alexandr Az
Гость
« : Февраль 20, 2011, 02:06 »

Добавляем строки в модель
Код:
beginInsertRows(коли-во записей)
//загрузка данных
endInsertRows

В общем шаблонный случай. Если кол-во вставляемых записей нам не известно, определяем буфер до вызова beginInsertRows, закачиваем данные, а между beginInsertRows и endInsertRows копируем в модель. Это шаблон. Что же у нас?

Делаем ли мы так:
Код:
//загрузка данных
beginInsertRows(коли-во записей)
endInsertRows
или по правилам не имеет значение.

Т.е. я вообще не знаю зачем эта пара методов, кроме как посыла сигнала о том, что данные изменились.

Мысль о том, что собака где то зарыта, заставляет делать правильно. Мало ли, где косяк вылезет. Может в будущей версии (если будет конечно) всё измениться.

А что же смущает..... !!!
Да исходники самой же Qt
Пример из fetchMore QSqlQuery:
Код:
q->beginInsertRows(QModelIndex(), bottom.row() + 1, newBottom.row());
bottom = newBottom;
q->endInsertRows();
Где bottom  - указатель на последнюю строку, ну, можете считать её номер.

Т.е. сидел какой то троль, думал думал, думал думал.  Шо ж туда запихнуть? Не запихнуть нельзя - скажут дурак, два парных метода, если их сделали, значит нужно. И запихнул. И вроде логично как бы. Ну вот изменил кол-во строк в модели и можно считать это загрузкой данных...... Мало ли, может где ещё этот bottom по дороге участвует.... Вообщем так и осталось не понятным, зачем же они!

« Последнее редактирование: Февраль 20, 2011, 02:15 от Alexandr Az » Записан
developer
Гость
« Ответ #1 : Февраль 20, 2011, 05:49 »

Кстати, мне тоже интересно
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #2 : Февраль 20, 2011, 07:55 »

q->beginInsertRows(...) - сообщает о том, что данные собираются изменится
bottom = newBottom; - кол-во данных изменилось
q->endInsertRows(); - сообщает об изменении
Записан

Юра.
Alexandr Az
Гость
« Ответ #3 : Февраль 20, 2011, 10:05 »

q->beginInsertRows(...) - сообщает о том, что данные собираются изменится
bottom = newBottom; - кол-во данных изменилось
q->endInsertRows(); - сообщает об изменении

Это и так понятно из моего первого поста. Напишите вы bottom = newBottom перед beginInsertRows  или внутри, не имеет значение.
Вот в чём вопрос. И так, переписываем:
Код:
1. bottom = newBottom; - кол-во данных изменилось
2. q->beginInsertRows(...) - сообщает о том, что данные собираются изменится
3. q->endInsertRows(); - сообщает об изменении
Все работает и теоретически проблема может произойти только в случае, если между 1-й и 2-й строчкой кода произойдёт событие с моделью, что невозможно.

Такая парная конструкция обычно использовалась для GUI - мы вставляем записи, но не хотим чтобы перерисовка происходила после вставки каждой. Но в данном случае мне не понятно.
« Последнее редактирование: Февраль 20, 2011, 10:13 от Alexandr Az » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #4 : Февраль 20, 2011, 10:25 »

>>или внутри, не имеет значение.
имеет, т.к. подключенные к модели объекты не будут ничего знать о предстоящем изменении
Записан

Юра.
Alexandr Az
Гость
« Ответ #5 : Февраль 20, 2011, 11:32 »

>>или внутри, не имеет значение.
имеет, т.к. подключенные к модели объекты не будут ничего знать о предстоящем изменении

Не важно, уже превращается в никому не нужную дискуссию. Вы не поняли сам вопрос. Концепция полностью понятна. Вы говорите очевидные вещи, разжёванные в самом вопросе.

Цитировать
имеет, т.к. подключенные к модели объекты не будут ничего знать о предстоящем изменении

Да и плевать что не знают. Узнают когда вызовем endInsertRows.

Приведу более практические размышления.
Реализовываем модель. К примеру пишем аналог QSqlQuery -  т.е. таблица. Между нашей пару методов изменяем кол-во строк.
Почему только кол-во строк? Есть несколько условий для данной модели, которые СИЛЬНО! упрощают реализацию:
1. Модель плоская (таблица).
2. Данные растут только вниз.

Что происходит: добавили данные, но модель об этом не знает. Увеличили кол-во строк - опа, модель узнала.
Если у нас дерево, да ещё и данные могут вставляться в различные уровни, такой простой вещью не обойтись, что меня не очень радует.

Если так не понятны мучения  - да работает всё и без этого. Если бы оно глючило или в документации было бы указано мне бы было проще. Да, судя по коду косяки могут быть, но только если модель в другом потоке.
« Последнее редактирование: Февраль 20, 2011, 11:44 от Alexandr Az » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #6 : Февраль 20, 2011, 13:05 »

>>добавили данные, но модель об этом не знает. Увеличили кол-во строк - опа, модель узнала.
не понял.
Добавили данные куда?
почему кол-во строк (где-то) не зависит от кол-ва данных?
Записан

Юра.
Alexandr Az
Гость
« Ответ #7 : Февраль 20, 2011, 13:15 »

>>добавили данные, но модель об этом не знает. Увеличили кол-во строк - опа, модель узнала.
не понял.
Добавили данные куда?
почему кол-во строк (где-то) не зависит от кол-ва данных?

Извиняюсь, как то тяжело пишу.
Код:
Загружаем данные в модель. Она о них не знает, потому что они лежат за пределами bottom
q->beginInsertRows(...) - сообщает о том, что данные собираются изменится
bottom = newBottom; - кол-во данных изменилось  - т.е. сказали модели, что у нас новое кол-во строк
q->endInsertRows(); - сообщает об изменении

Записан
Akon
Гость
« Ответ #8 : Февраль 20, 2011, 14:05 »

beginInsertRows()/endInsertRows() и beginRemoveRows()/endRemoveRows() - двухфазное оповещение об изменении, иногда необходимое.

Зачем это нужно? Допустим, в модели всего две строки, обе выделены (см. QItemSelectionModel). Далее добавляем новую строку в середину, т.е. выделенными должны быть исходные строки 1 и 3.

Теперь рассмотрим двух клиентов модели - 1-й уже упомянутый QItemSelectionModel, 2-й - тот, который использует помимо модели также и первого клиента, типичный пример - QAbstractItemView (см. QAbstractItemView::setModel(), QAbstractItemView::setSelectionModel()). Пусть будет только однофазное оповещение о добавлении строки по endInsertRows()  (сигнал rowsInserted()).

В этом случае возможно, что QAbstractItemView первым обработает сигнал и отрисует выделение на исходный строках 1 и 2 (а не 2 и 3!), т.к. QItemSelectionModel еще не обновилась (т.е. есть момент времени, в который клиент имеет некорректную информацию о выделенных строках!). Если же QItemSelectionModel обработает сигнал первой, то проблемы не будет. Т.о. вы всегда должны следить за порядком вызова слотов клиентов, что крайне непрактично (формально порядок вызова слотов вообще не определен!).

Чтобы исключить данную проблему используется две фазы (два сигнала). QItemSelectionModel использует первый сигнал (rowsAboutToBeInserted(), испускаемый beginInsertRows()) и всегда обновляется до любых зависящих от нее клиентов.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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