В классе QAbstractItemView есть метод setModel(QAbstractItemModel *model)
setSelectionModel(new QItemSelectionModel(d->model, this));
Я мало что понял. Вопрос заключается в том почему тролли не сделали автоматическое удаление модели выделения и почему не используют старую модель выделения (старая это какая, которая была заменена новой, но осталась висеть в памяти и должна использоваться, если конструктор новой не сработал или что?).
Кстати интересно. Написано, что setModel каждый раз устанавливает новую QItemSelectionModel, т.е. старая модель все-таки должна удаляться Qt иначе будет утечка памяти...
В 4.4.3 ситуация таже. Все экземпляры QItemSelectionModel удаляются только в момент удаления компонентов на базе QAbstractItemView, т.к. именно он является предком. Т.е. только когда удаляются QColumnView, QHeaderView, QListView, QTableView, и QTreeView. Отсюда можно сделать вывод, что setModel в цикле на одну вьюху рано или поздно закончится плачевно. Я решил провести эксперимент таким образом:
QTreeView *tree = new QTreeView(this);
forever
{
tree->setModel(0);
}
forever
{
QTreeView *tree = new QTreeView(this);
tree->setModel(0);
delete tree;
}
страшного ничего в этом нет. просто на момент установки новой модели "старая" селекшн-модель может ещё использоваться и, поскольку мы не хотим сегфолта, модель не удаляем (подобное часто встречается в сорцах кутэ) - на мой взгляд это лучше, чем пол-дюжины проверок в каждом методе (привет, гтк)!
если нужно часто "передёргивать" модель-источник и программист твёрдо уверен, что селекшн-модель в момент установки модели-источника нигде не используется, программист может смело делать так:
QTreeView *tree = new QTreeView(this);
forever
{
QItemSelectionModel* sm = tree->selectionModel();
tree->setModel(0);
sm->deleteLater;
}
Интересно почему Qt сама не делает deleteLater(). Или почему нет предупреждения о возможной утечке памяти. Скорее всего потому, что вьюха не рассчитана на такое использование модели. Видимо предполагается, что модель должна быть одна-две и вся работа по заполнению/очистки модели должна происходить только с одним экземпляром.
QTreeView *tree = new QTreeView(this);
forever
{
QItemSelectionModel* sm = tree->selectionModel();
tree->setModel(0);
// предполагаем, что в setModel(...) выполнится sm->deleteLater;
tree->setSelectionModel(sm); // типа, восстановили состояние выбора до сброса модели
}
я думаю, что можно было бы продолжить использовать имеющуюся модель выбора. Т.к. представления должны работать в главном потоке и как следствие связанные с ними модели. Поэтому если програмист меняет модель данных, то одновременно с этим он не работает с моделью выбора. Хотя, в прочем, я еще полноценно с модель/представление не работал, может в этом и нет особой надобности.
> А где ты увидел выход в eventloop?
согласен, с примером оплошал. но и tree->setSelectionModel(sm) не обязательно может выполнятся синхронно
правда, это уже абсурдинкой попахивает...наверное, просто не рассчитана вьюха на подобные передёргивания источника - и всё тут...
> Интересно, есть ли возможность без наследования получить список всех QObject'ов в программе или по крайней мере создать такой список? При этом не обязательно, что QObject имеет parent'a или является QWidget'ом.
see src/corelib/kernel/qobject.cpp:
/*
let's see src/corelib/kernel/qobject.cpp:
Q_GLOBAL_STATIC (QObjectSet, allObjects)
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *object)
QWriteLocker locker(qt_object_read_write_lock());
QObjectSet *set = allObjects();
if (set)
set->insert(object);
//...
QObject::QObject(QObject *parent)
: d_ptr(new QObjectPrivate)
Q_D(QObject);
qt_addObject(d_ptr->q_ptr = this);
//...
*/
я и не говорил, что к нему достучаться. в лучшем случае из него можно выдоить виджеты без родителя...
но в отладочных целях можно влезть в код и наделать там гадостей
Подскажите пожалуйста что выбрать? Устанавливаю в TableView новую ItemSelectionModel. Так как старая ItemSelectionModel больше не нужна, то требуется её удалить. Сейчас в документации последних версий уже описывается в каких случаях это нужно делать и предлагается для этого два способа:
QItemSelectionModel *OldSelectionModel = view->selectionModel();
view->setSelectionModel(new MyItemSelectionModel(view->model));
delete OldSelectionModel;
view->selectionModel()->deleteLater();
view->setSelectionModel(new MyItemSelectionModel(view->model));
а может быть правильно так:
QItemSelectionModel *OldSelectionModel = view->selectionModel();
view->setSelectionModel(new MyItemSelectionModel(view->model));
OldSelectionModel->deleteLater();
разница именно в моменте удалении непосредственно самого объекта, в случае оператора delete объект будет удален сразу, в случае удаления посредством вызова deleteLater объект удалится, в момент передачи управления основному циклу обработки сообщений приложения, т.е. при таком вызове указатель на объект как правило еще валиден в рамках вызывающего участка кода. Что лучше использовать уже дело вкуса, если вариант с вызовом delete решает нужную задачу, то я выберу его.
В документации для QAbstractItemView::setSelectionModel предлагается использовать deleteLater(), но вероятно имеется ввиду общий, универсальный случай. В моём случае, после задания TableView->setModel, я сразу в TableView->setSelectionModel задаю MyItemSelectionModel, а ItemSelectionModel созданная по умолчанию мне совсем не нужна и, поэтому я думаю, что её можно удалить с помощью просто delete.
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)