[Qt-interest] QSortProxyModel - row being filtered before it is inserted
Laura Arhire
larhire at gmail.com
Wed Feb 3 16:02:03 CET 2010
Hello
I've got a custom, lazy-loaded model which can be used in tree views and
list views. The model is very similar to a directory structure (it contains
folders/files sort of objects). The lazy population is performed using the
canFetchMode and fetchMore methods.
In order to show the model properly for each view, I'm using a filter proxy:
this proxy filters the structure in such a way that:
* list views (which just show one "directory" at a time) show all items
* tree views show the whole structure, but only "directories"
The normal model works fine, I've tested it with the model test in qt labs
and separately without a filter model. However, if I attach a "tree" proxy
to it, I have some trouble when fetching items. It seems that the proxy
model's filterAcceptsRow method is called as a result of the call to
beginInsertRows in the target mode. This means that the row itself is not
yet added to the model, which causes a SIGSEG.
I think I'm missing something related to the implementation, but I haven't
been able to find anything relevant on the discussion lists and on the web.
Here is the relevant stacktrace I get:
Program received signal SIGSEGV, Segmentation fault.
0x0048efd4 in ExplorerModel::get_child_explorer_item (this=0xcdbbc48,
row=0, parent=@0x27cb14) at browser/qt/src/ExplorerModel.cpp:321
321 item->add_child(); // note - this is here so we can
crash & get a stacktrace when the filter model attempts to filter rows
before they're added
Current language: auto; currently c++
(gdb) bt
#0 0x0048efd4 in ExplorerModel::get_child_explorer_item (
this=0xcdbbc48, row=0, parent=@0x27cb14)
at browser/qt/src/ExplorerModel.cpp:321
#1 0x00497ef6 in ModelSortFilterProxy::filterAcceptsRow (
this=0xdc54258, row=0, parent=@0x27cb14)
at browser/qt/src/ModelSortFilterProxy.cpp:159
#2 0x02cca1c1 in QSortFilterProxyModelPrivate::create_mapping (
this=0xdc54998, source_parent=@0x27cb14)
at itemviews\qsortfilterproxymodel.cpp:291
#3 0x02ccdbf6 in
QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted
(this=0xdc54998, source_parent=@0x27cb14, start=0, end=0)
at itemviews\qsortfilterproxymodel.cpp:1236
#4 0x02cd1acb in QSortFilterProxyModel::qt_metacall (this=0xdc54258,
_c=QMetaObject::InvokeMetaMethod, _id=11, _a=0x27ca48)
at tmp/moc/debug_shared/moc_qsortfilterproxymodel.cpp:134
#5 0x00496d64 in ModelSortFilterProxy::qt_metacall (this=0xdc54258,
_c=QMetaObject::InvokeMetaMethod, _id=36, _a=0x27ca48)
at browser/qt/include/ModelSortFilterProxy_moc.cpp:74
#6 0x6a20181c in QMetaObject::metacall (object=0xdc54258,
cl=QMetaObject::InvokeMetaMethod, idx=36, argv=0x27ca48)
at kernel\qmetaobject.cpp:237
#7 0x6a2115b5 in QMetaObject::activate (sender=0xcdbbc48, m=0x6a33aa40,
local_signal_index=4, argv=0x27ca48) at kernel\qobject.cpp:3267
#8 0x6a24cef2 in QAbstractItemModel::rowsAboutToBeInserted
(this=0xcdbbc48,
_t1=@0x27cb14, _t2=0, _t3=0)
at tmp\moc\debug_shared\moc_qabstractitemmodel.cpp:174
#9 0x6a1f89e6 in QAbstractItemModel::beginInsertRows (this=0xcdbbc48,
parent=@0x27cb14, first=0, last=0) at kernel\qabstractitemmodel.cpp:2393
#10 0x0048f421 in ExplorerModel::fetchMore (this=0xcdbbc48,
parent=@0x27cb14) at browser/qt/src/ExplorerModel.cpp:382
#11 0x02cd02c6 in QSortFilterProxyModel::fetchMore (this=0xdc54258,
parent=@0x27cb88) at itemviews\qsortfilterproxymodel.cpp:1922
#12 0x02c95481 in QTreeViewPrivate::layout (this=0xdc4d950, i=0)
at itemviews\qtreeview.cpp:3143
#13 0x02c94283 in QTreeViewPrivate::expand (this=0xdc4d950, item=0,
emitSignal=true) at itemviews\qtreeview.cpp:2943
#14 0x02c8cf0e in QTreeViewPrivate::expandOrCollapseItemAtPos (
this=0xdc4d950, pos=@0x27d704) at itemviews\qtreeview.cpp:1320
#15 0x02c8f59e in QTreeView::mousePressEvent (this=0xdb0e088,
event=0x27d6f4)
at itemviews\qtreeview.cpp:1817
And I have the following relevant methods :
void ExplorerModel::fetchMore(const QModelIndex& parent )
{
ExplorerItem *item = get_explorer_item(parent);
if (item != NULL && item->get_children_count() > 0)
{
beginInsertRows(parent, 0, item->get_children_count() - 1);
item->populate();
endInsertRows();
}
}
bool ExplorerModel::canFetchMore(const QModelIndex& parent, ViewType view)
const
{
if (parent.isValid())
{
ExplorerItem *item = get_explorer_item(parent);
return !item->is_populated() && item->has_children(view);
}
return false; // root always fetched
}
bool ModelSortFilterProxy::filterAcceptsRow(int row, const QModelIndex
&parent) const
{
bool result = true;
if (this->view_type == ExplorerModel::TREE_VIEW)
{
ExplorerItem *item = this->model->get_child_explorer_item(row,
parent);
result = item->is_dir();
}
return result;
}
bool ModelSortFilterProxy::canFetchMore(const QModelIndex &parent) const
{
return model->canFetchMore(mapToSource(parent), this->view_type);
}
>From the stack trace, the filterAcceptsRow seems to be called when I call
beginInsertRows on the target model - and if I look at Qt source code, that
is indeed what should happen. But I don't think this should happen - I also
know how to fix this, since I don't know anything about the rows being
populated until after they are populated.
Can anyone spot what I'm missing?
Thanks,
Laura
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20100203/3c0ac704/attachment.html
More information about the Qt-interest-old
mailing list