Название: Тонкости InterView Отправлено: xintrea от Сентябрь 15, 2010, 20:54 Здравствуйте!
Всем нам известен режим связывания модели и представления, который в Qt называется InterView. В SDK есть готовые примеры. И что-то я не могу понять одной вещи. Есть два метода (можно посмотреть в примере): Код
Так вот, в rowCount() нет проверки на валидность индекса. В результате, даже если индекс невалидный, из rowCount() идет тупо вызов getItem(). В getItem() в случае невалидного индекса возвращается rootItem (!) - зачем?? Но самое интересное возникает тогда, когда пытаешься добавить проверку валидности в rowCount(). Например так: Код
После такого исправления, дерево перестает отображаться вообще. Дебаг показал, что это происходит из-за того, что представление запрашивает количество строк в корне дерева путем запрашивания у модели метода rowCount(), передавая ему невалидный индекс (!) . И ожидает, что если индекс невалидный, то будет возвращено количество строк корневого элемента (а не 0). Зачем так?? Я хотел переделать getItem() таким образом, чтобы он возвращал NULL а не rootItem в случае невалидного индекса. Но оказывается, это сделать нельзя по вышеописанной причине. Вопрос - почему так сделано, и есть ли какой-нибудь способ правильно работать с невалидными индексами? То есть не возвращать rootItem в случае невалидного индекса, а возвращать NULL, как положено в любом нормальном коде. Название: Re: Тонкости InterView Отправлено: Авварон от Сентябрь 15, 2010, 21:05 считается что невалидный индекс - это корень. Чем вас это соглашение напрягает?
Название: Re: Тонкости InterView Отправлено: lit-uriy от Сентябрь 15, 2010, 21:12 его видимо не напрягает, а просто он не читал доку внимательно, там и картинка (http://doc.crossplatform.ru/qt/4.6.x/model-view-model.html) есть
Название: Re: Тонкости InterView Отправлено: xintrea от Сентябрь 15, 2010, 21:16 считается что невалидный индекс - это корень. Чем вас это соглашение напрягает? Тем, что например при удалении веток в дереве, если пользователем помечена она ветка и пара ее же подветок (глупо, но такая ситуация возможна), то к моменту удаления подветки у нее получается невалидный индекс (ибо родительская ветка уже удалена). Связанные с веткой данные должны очищаться через, например, setData(). Но setData тоже работает через getItem(), а getItem() возвращает корень дерева в случае невалидного индекса. И происходит удаление данных в корне. Название: Re: Тонкости InterView Отправлено: Авварон от Сентябрь 15, 2010, 21:18 ну так вам надо снаружи вьюхи проверять индекс на валидность и не удалять невалидные индексы. Кроме того, эту проверку можно воткнуть в ваш метод remove(QModelIndex) (это корректно, тк рут удалить нельзя)
Название: Re: Тонкости InterView Отправлено: xintrea от Сентябрь 15, 2010, 21:21 его видимо не напрягает, а просто он не читал доку внимательно, там и картинка (http://doc.crossplatform.ru/qt/4.6.x/model-view-model.html) есть Не, когда сказали - я вспомнил, просто год с Qt не возился, все позабыл. На лицо неправильная объектная декомпозиция, в которой смешаны понятия "корень" и "несуществующий элемент". Название: Re: Тонкости InterView Отправлено: BRE от Сентябрь 15, 2010, 21:27 На лицо неправильная объектная декомпозиция, в которой смешаны понятия "корень" и "несуществующий элемент". Ну так корень и есть несуществующий элемент.Название: Re: Тонкости InterView Отправлено: xintrea от Сентябрь 15, 2010, 21:38 Ну так корень и есть несуществующий элемент. Нет, корень - это корень. Можете считать его особым несуществующим элементом. Должна быть возможность отличать корень и несуществующий элемент. А такой возможности нет. Название: Re: Тонкости InterView Отправлено: BRE от Сентябрь 15, 2010, 22:03 Нет, корень - это корень. Можете считать его особым несуществующим элементом. Должна быть возможность отличать корень и несуществующий элемент. А такой возможности нет. Да как бы все проще.С точки зрения QModelIndex, не валидный индекс это индекс с row < 0 или column < 0 или model == 0. Такой индекс можно создать вызвав конструктор по умолчанию, а он (не считая конструктора копирования) единственный публичный. При его передачи в качестве parent, считается что имеется ввиду root элемент. Это я к чему, что проверка isValid покажет true, для созданного индекса даже если такого элемента уже нет, главное что бы соблюдалось вышеуказанное условие. А для проверки корректности ячейки можно попробовать использовать метод: bool QAbstractItemModel::hasIndex ( int row, int column, const QModelIndex & parent = QModelIndex() ) const Название: Re: Тонкости InterView Отправлено: GraninAS от Сентябрь 28, 2010, 10:11 считается что невалидный индекс - это корень. Чем вас это соглашение напрягает? Тем, что например при удалении веток в дереве, если пользователем помечена она ветка и пара ее же подветок (глупо, но такая ситуация возможна), то к моменту удаления подветки у нее получается невалидный индекс (ибо родительская ветка уже удалена). Связанные с веткой данные должны очищаться через, например, setData(). Но setData тоже работает через getItem(), а getItem() возвращает корень дерева в случае невалидного индекса. И происходит удаление данных в корне. В древовидной структуре удаление должно быть рекурсивным, тогда проблем не возникнет. |