Qt-interest Archive, January 2007
Filtering a composite-based model
Message 1 in thread
Hello!
My custom tree model implementation (QAbstractItemModel subclass) is
structured as a composite, similar to a file system: there's folders
which can contain other folders as well as files. Now I'd like to write
a filter model (QSortFilterProxyModel subclass) which only allows the
leaf nodes of the tree (i.e. the files) to be displayed, but no
container nodes (i.e. the folders). E.g. if a folder contains two files
and a sub-folder, only the two files should be accepted by the filter model.
Any idea how a #filterAcceptsRow implementation would look like for
these requirements?
Many thanks,
M
--
[ signature omitted ]
Message 2 in thread
In filterAcceptRow, return true if qmi.model()->rowCount( qmi ) == 0
Where qmi is the QModelIndex sent into the filterAcceptRow
Scott
> -----Original Message-----
> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> Sent: Tuesday, January 23, 2007 5:14 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Filtering a composite-based model
>
> Hello!
>
> My custom tree model implementation (QAbstractItemModel subclass) is
> structured as a composite, similar to a file system: there's folders
> which can contain other folders as well as files. Now I'd like to
write
> a filter model (QSortFilterProxyModel subclass) which only allows the
> leaf nodes of the tree (i.e. the files) to be displayed, but no
> container nodes (i.e. the folders). E.g. if a folder contains two
files
> and a sub-folder, only the two files should be accepted by the filter
> model.
>
> Any idea how a #filterAcceptsRow implementation would look like for
> these requirements?
>
> Many thanks,
> M
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 3 in thread
Scott Aron Bloom wrote:
> In filterAcceptRow, return true if qmi.model()->rowCount( qmi ) == 0
>
> Where qmi is the QModelIndex sent into the filterAcceptRow
>
> Scott
Hi Scott, thanks for your answer.
Good idea, but I found two problems when trying it out: first, not all
elements without children are leaf nodes of the tree, they could as well
be empty containers. Second (and more severe): if no container is
accepted by the filter, the model will never provide any data because
the root index itself is *not* accepted, and thus no child elements are
accessible.
Any idea how to get over these problems?
Regards,
M
>> -----Original Message-----
>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
>> Sent: Tuesday, January 23, 2007 5:14 AM
>> To: qt-interest@xxxxxxxxxxxxx
>> Subject: Filtering a composite-based model
>>
>> Hello!
>>
>> My custom tree model implementation (QAbstractItemModel subclass) is
>> structured as a composite, similar to a file system: there's folders
>> which can contain other folders as well as files. Now I'd like to
> write
>> a filter model (QSortFilterProxyModel subclass) which only allows the
>> leaf nodes of the tree (i.e. the files) to be displayed, but no
>> container nodes (i.e. the folders). E.g. if a folder contains two
> files
>> and a sub-folder, only the two files should be accepted by the filter
>> model.
>>
>> Any idea how a #filterAcceptsRow implementation would look like for
>> these requirements?
>>
>> Many thanks,
>> M
>>
>> --
>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
>> "unsubscribe" in the subject or the body.
>> List archive and information: http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 4 in thread
Sure.... Does the base model know if should be filtered? I assume so...
Add a custom role, where you could ask the model or modelindex if it
should be shown.
Index.data( CustomFilterRole ).toBool()
In the models data method, you can then return the appropriate value.
Scott
> -----Original Message-----
> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> Sent: Wednesday, January 24, 2007 1:02 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Filtering a composite-based model
>
> Scott Aron Bloom wrote:
> > In filterAcceptRow, return true if qmi.model()->rowCount( qmi ) == 0
> >
> > Where qmi is the QModelIndex sent into the filterAcceptRow
> >
> > Scott
>
> Hi Scott, thanks for your answer.
>
> Good idea, but I found two problems when trying it out: first, not all
> elements without children are leaf nodes of the tree, they could as
well
> be empty containers. Second (and more severe): if no container is
> accepted by the filter, the model will never provide any data because
> the root index itself is *not* accepted, and thus no child elements
are
> accessible.
>
> Any idea how to get over these problems?
>
> Regards,
> M
>
>
> >> -----Original Message-----
> >> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> >> Sent: Tuesday, January 23, 2007 5:14 AM
> >> To: qt-interest@xxxxxxxxxxxxx
> >> Subject: Filtering a composite-based model
> >>
> >> Hello!
> >>
> >> My custom tree model implementation (QAbstractItemModel subclass)
is
> >> structured as a composite, similar to a file system: there's
folders
> >> which can contain other folders as well as files. Now I'd like to
> > write
> >> a filter model (QSortFilterProxyModel subclass) which only allows
the
> >> leaf nodes of the tree (i.e. the files) to be displayed, but no
> >> container nodes (i.e. the folders). E.g. if a folder contains two
> > files
> >> and a sub-folder, only the two files should be accepted by the
filter
> >> model.
> >>
> >> Any idea how a #filterAcceptsRow implementation would look like for
> >> these requirements?
> >>
> >> Many thanks,
> >> M
> >>
> >> --
> >> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
with
> >> "unsubscribe" in the subject or the body.
> >> List archive and information:
http://lists.trolltech.com/qt-interest/
> >
> > --
> > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
with
> "unsubscribe" in the subject or the body.
> > List archive and information:
http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 5 in thread
Scott Aron Bloom wrote:
> Sure.... Does the base model know if should be filtered? I assume so...
>
> Add a custom role, where you could ask the model or modelindex if it
> should be shown.
>
> Index.data( CustomFilterRole ).toBool()
>
> In the models data method, you can then return the appropriate value.
>
> Scott
Right, this would get round the problem of distinguishing empty
container nodes from leaf nodes, but not the second one.
To clarify what I think of as the problem #2: in the following tree, A,
B and C are containers and d is a leaf.
A
+-B
+-C
+-d
If I install this tree model on a view and set B to be the root index,
I'd expect it to only show d. But I can't even get as far as to map the
tree model's index B to the filter model (I'd need to do so because the
view's model is actually the filter, not the tree model) because the
#mapFromSource method returns an invalid index: for the filter model,
index B does not exist because it would be filtered out as a non-leaf;
no B, no children of B, no d...
That's what I came up with when experimenting. Perhaps I'm missing some
important point (happens a lot to me)... Any suggestions?
M
>> -----Original Message-----
>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
>> Sent: Wednesday, January 24, 2007 1:02 AM
>> To: qt-interest@xxxxxxxxxxxxx
>> Subject: Re: Filtering a composite-based model
>>
>> Scott Aron Bloom wrote:
>>> In filterAcceptRow, return true if qmi.model()->rowCount( qmi ) == 0
>>>
>>> Where qmi is the QModelIndex sent into the filterAcceptRow
>>>
>>> Scott
>> Hi Scott, thanks for your answer.
>>
>> Good idea, but I found two problems when trying it out: first, not all
>> elements without children are leaf nodes of the tree, they could as
> well
>> be empty containers. Second (and more severe): if no container is
>> accepted by the filter, the model will never provide any data because
>> the root index itself is *not* accepted, and thus no child elements
> are
>> accessible.
>>
>> Any idea how to get over these problems?
>>
>> Regards,
>> M
>>
>>
>>>> -----Original Message-----
>>>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
>>>> Sent: Tuesday, January 23, 2007 5:14 AM
>>>> To: qt-interest@xxxxxxxxxxxxx
>>>> Subject: Filtering a composite-based model
>>>>
>>>> Hello!
>>>>
>>>> My custom tree model implementation (QAbstractItemModel subclass)
> is
>>>> structured as a composite, similar to a file system: there's
> folders
>>>> which can contain other folders as well as files. Now I'd like to
>>> write
>>>> a filter model (QSortFilterProxyModel subclass) which only allows
> the
>>>> leaf nodes of the tree (i.e. the files) to be displayed, but no
>>>> container nodes (i.e. the folders). E.g. if a folder contains two
>>> files
>>>> and a sub-folder, only the two files should be accepted by the
> filter
>>>> model.
>>>>
>>>> Any idea how a #filterAcceptsRow implementation would look like for
>>>> these requirements?
>>>>
>>>> Many thanks,
>>>> M
>>>>
>>>> --
>>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> with
>>>> "unsubscribe" in the subject or the body.
>>>> List archive and information:
> http://lists.trolltech.com/qt-interest/
>>> --
>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> with
>> "unsubscribe" in the subject or the body.
>>> List archive and information:
> http://lists.trolltech.com/qt-interest/
>> --
>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
>> "unsubscribe" in the subject or the body.
>> List archive and information: http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 6 in thread
Make sure your setting the model index from the appropriate model...
More then once, I have been burned by working with a model index from a
source model when the view is pointed to a proxy (and vice versa)
That's probably causing your invalid index issue.
But if you get the root model index from the source, do a map from
source, your filter function should get called, and that model index
custom role should return true.
Scott
> -----Original Message-----
> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> Sent: Wednesday, January 24, 2007 1:28 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Filtering a composite-based model
>
> Scott Aron Bloom wrote:
> > Sure.... Does the base model know if should be filtered? I assume
so...
> >
> > Add a custom role, where you could ask the model or modelindex if it
> > should be shown.
> >
> > Index.data( CustomFilterRole ).toBool()
> >
> > In the models data method, you can then return the appropriate
value.
> >
> > Scott
>
>
> Right, this would get round the problem of distinguishing empty
> container nodes from leaf nodes, but not the second one.
>
> To clarify what I think of as the problem #2: in the following tree,
A,
> B and C are containers and d is a leaf.
>
> A
> +-B
> +-C
> +-d
>
> If I install this tree model on a view and set B to be the root index,
> I'd expect it to only show d. But I can't even get as far as to map
the
> tree model's index B to the filter model (I'd need to do so because
the
> view's model is actually the filter, not the tree model) because the
> #mapFromSource method returns an invalid index: for the filter model,
> index B does not exist because it would be filtered out as a non-leaf;
> no B, no children of B, no d...
>
> That's what I came up with when experimenting. Perhaps I'm missing
some
> important point (happens a lot to me)... Any suggestions?
>
> M
>
>
>
> >> -----Original Message-----
> >> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> >> Sent: Wednesday, January 24, 2007 1:02 AM
> >> To: qt-interest@xxxxxxxxxxxxx
> >> Subject: Re: Filtering a composite-based model
> >>
> >> Scott Aron Bloom wrote:
> >>> In filterAcceptRow, return true if qmi.model()->rowCount( qmi ) ==
0
> >>>
> >>> Where qmi is the QModelIndex sent into the filterAcceptRow
> >>>
> >>> Scott
> >> Hi Scott, thanks for your answer.
> >>
> >> Good idea, but I found two problems when trying it out: first, not
all
> >> elements without children are leaf nodes of the tree, they could as
> > well
> >> be empty containers. Second (and more severe): if no container is
> >> accepted by the filter, the model will never provide any data
because
> >> the root index itself is *not* accepted, and thus no child elements
> > are
> >> accessible.
> >>
> >> Any idea how to get over these problems?
> >>
> >> Regards,
> >> M
> >>
> >>
> >>>> -----Original Message-----
> >>>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> >>>> Sent: Tuesday, January 23, 2007 5:14 AM
> >>>> To: qt-interest@xxxxxxxxxxxxx
> >>>> Subject: Filtering a composite-based model
> >>>>
> >>>> Hello!
> >>>>
> >>>> My custom tree model implementation (QAbstractItemModel subclass)
> > is
> >>>> structured as a composite, similar to a file system: there's
> > folders
> >>>> which can contain other folders as well as files. Now I'd like to
> >>> write
> >>>> a filter model (QSortFilterProxyModel subclass) which only allows
> > the
> >>>> leaf nodes of the tree (i.e. the files) to be displayed, but no
> >>>> container nodes (i.e. the folders). E.g. if a folder contains two
> >>> files
> >>>> and a sub-folder, only the two files should be accepted by the
> > filter
> >>>> model.
> >>>>
> >>>> Any idea how a #filterAcceptsRow implementation would look like
for
> >>>> these requirements?
> >>>>
> >>>> Many thanks,
> >>>> M
> >>>>
> >>>> --
> >>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> > with
> >>>> "unsubscribe" in the subject or the body.
> >>>> List archive and information:
> > http://lists.trolltech.com/qt-interest/
> >>> --
> >>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> > with
> >> "unsubscribe" in the subject or the body.
> >>> List archive and information:
> > http://lists.trolltech.com/qt-interest/
> >> --
> >> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
with
> >> "unsubscribe" in the subject or the body.
> >> List archive and information:
http://lists.trolltech.com/qt-interest/
> >
> > --
> > To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
with
> "unsubscribe" in the subject or the body.
> > List archive and information:
http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 7 in thread
Scott Aron Bloom wrote:
> Make sure your setting the model index from the appropriate model...
> More then once, I have been burned by working with a model index from a
> source model when the view is pointed to a proxy (and vice versa)
> That's probably causing your invalid index issue.
>
> But if you get the root model index from the source, do a map from
> source, your filter function should get called, and that model index
> custom role should return true.
>
> Scott
Ups, indeed, what I forgot was to set the filter model's #sourceModel
before doing the #mapFromSource....
Still, it doesn't work too well. Here's some demo code using QDirModel.
The filter extracts the item's path and checks if it is a file or a
directory. If it's a file, the row is accepted (this should be
equivalent to using a custom role for distinguishing between containers
and leafs):
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent)
const {
QModelIndex index = source_parent.child(source_row, 0);
QString path = index.data(QDirModel::FilePathRole).toString();
return QFileInfo(path).isFile();
}
In main, I create the models and the root index for the view. The second
assertion fails because the filter model seems to prevent the creation
of a mapped index (if #filterAcceptsRow always returns true, the index
mapping works):
QDirModel model;
LeafElementFilterModel filterModel;
filterModel.setSourceModel(&model);
QModelIndex root = model.index("C:/Windows");
Q_ASSERT(root.isValid());
QModelIndex filterRoot = filterModel.mapFromSource(root);
Q_ASSERT(filterRoot.isValid());
I think what happens is this: when I #mapFromSource the index from the
QDirModel, the filter model traverses its source model from the root
index. But since the index representing "C:/Windows" is be filtered out
(it's not a file after all), that index doesn't exist for the filter
model and thus no mapping can be created...
I'm starting to think this problem has no solution...
Best,
M
>> -----Original Message-----
>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
>> Sent: Wednesday, January 24, 2007 1:28 AM
>> To: qt-interest@xxxxxxxxxxxxx
>> Subject: Re: Filtering a composite-based model
>>
>> Scott Aron Bloom wrote:
>>> Sure.... Does the base model know if should be filtered? I assume
> so...
>>> Add a custom role, where you could ask the model or modelindex if it
>>> should be shown.
>>>
>>> Index.data( CustomFilterRole ).toBool()
>>>
>>> In the models data method, you can then return the appropriate
> value.
>>> Scott
>>
>> Right, this would get round the problem of distinguishing empty
>> container nodes from leaf nodes, but not the second one.
>>
>> To clarify what I think of as the problem #2: in the following tree,
> A,
>> B and C are containers and d is a leaf.
>>
>> A
>> +-B
>> +-C
>> +-d
>>
>> If I install this tree model on a view and set B to be the root index,
>> I'd expect it to only show d. But I can't even get as far as to map
> the
>> tree model's index B to the filter model (I'd need to do so because
> the
>> view's model is actually the filter, not the tree model) because the
>> #mapFromSource method returns an invalid index: for the filter model,
>> index B does not exist because it would be filtered out as a non-leaf;
>> no B, no children of B, no d...
>>
>> That's what I came up with when experimenting. Perhaps I'm missing
> some
>> important point (happens a lot to me)... Any suggestions?
>>
>> M
>>
>>
>>
>>>> -----Original Message-----
>>>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
>>>> Sent: Wednesday, January 24, 2007 1:02 AM
>>>> To: qt-interest@xxxxxxxxxxxxx
>>>> Subject: Re: Filtering a composite-based model
>>>>
>>>> Scott Aron Bloom wrote:
>>>>> In filterAcceptRow, return true if qmi.model()->rowCount( qmi ) ==
>
> 0
>>>>> Where qmi is the QModelIndex sent into the filterAcceptRow
>>>>>
>>>>> Scott
>>>> Hi Scott, thanks for your answer.
>>>>
>>>> Good idea, but I found two problems when trying it out: first, not
> all
>>>> elements without children are leaf nodes of the tree, they could as
>>> well
>>>> be empty containers. Second (and more severe): if no container is
>>>> accepted by the filter, the model will never provide any data
> because
>>>> the root index itself is *not* accepted, and thus no child elements
>>> are
>>>> accessible.
>>>>
>>>> Any idea how to get over these problems?
>>>>
>>>> Regards,
>>>> M
>>>>
>>>>
>>>>>> -----Original Message-----
>>>>>> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
>>>>>> Sent: Tuesday, January 23, 2007 5:14 AM
>>>>>> To: qt-interest@xxxxxxxxxxxxx
>>>>>> Subject: Filtering a composite-based model
>>>>>>
>>>>>> Hello!
>>>>>>
>>>>>> My custom tree model implementation (QAbstractItemModel subclass)
>>> is
>>>>>> structured as a composite, similar to a file system: there's
>>> folders
>>>>>> which can contain other folders as well as files. Now I'd like to
>>>>> write
>>>>>> a filter model (QSortFilterProxyModel subclass) which only allows
>>> the
>>>>>> leaf nodes of the tree (i.e. the files) to be displayed, but no
>>>>>> container nodes (i.e. the folders). E.g. if a folder contains two
>>>>> files
>>>>>> and a sub-folder, only the two files should be accepted by the
>>> filter
>>>>>> model.
>>>>>>
>>>>>> Any idea how a #filterAcceptsRow implementation would look like
> for
>>>>>> these requirements?
>>>>>>
>>>>>> Many thanks,
>>>>>> M
>>>>>>
>>>>>> --
>>>>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
>>> with
>>>>>> "unsubscribe" in the subject or the body.
>>>>>> List archive and information:
>>> http://lists.trolltech.com/qt-interest/
>>>>> --
>>>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
>>> with
>>>> "unsubscribe" in the subject or the body.
>>>>> List archive and information:
>>> http://lists.trolltech.com/qt-interest/
>>>> --
>>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> with
>>>> "unsubscribe" in the subject or the body.
>>>> List archive and information:
> http://lists.trolltech.com/qt-interest/
>>> --
>>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> with
>> "unsubscribe" in the subject or the body.
>>> List archive and information:
> http://lists.trolltech.com/qt-interest/
>> --
>> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
>> "unsubscribe" in the subject or the body.
>> List archive and information: http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 8 in thread
On 24.01.07 11:10:19, Martin wrote:
> Scott Aron Bloom wrote:
> > Make sure your setting the model index from the appropriate model...
> > More then once, I have been burned by working with a model index from a
> > source model when the view is pointed to a proxy (and vice versa)
> > That's probably causing your invalid index issue.
> >
> > But if you get the root model index from the source, do a map from
> > source, your filter function should get called, and that model index
> > custom role should return true.
>
> bool filterAcceptsRow(int source_row, const QModelIndex &source_parent)
> const {
> QModelIndex index = source_parent.child(source_row, 0);
> QString path = index.data(QDirModel::FilePathRole).toString();
> return QFileInfo(path).isFile();
> }
Hmm, according to your OP this is not the right way, I mean you don't
want to filter out directories that have subdirs or files. The last line
shoule be something along this:
if( QFileInfo(path).isFile() )
return true;
else {
return QDir(path).entryList( QStringList() << "*" ).isEmpty();
}
Which first checks for file/dir (not on non-windows platforms there are
elements that are neither files nor dirs, so you might also want to
check for symlinks). If its a dir it checks wether the dir has any
children and if so it doesn't filter the dir out.
Andreas
--
[ signature omitted ]
Message 9 in thread
Andreas Pakulat wrote:
> On 24.01.07 11:10:19, Martin wrote:
>> Scott Aron Bloom wrote:
>>> Make sure your setting the model index from the appropriate model...
>>> More then once, I have been burned by working with a model index from a
>>> source model when the view is pointed to a proxy (and vice versa)
>>> That's probably causing your invalid index issue.
>>>
>>> But if you get the root model index from the source, do a map from
>>> source, your filter function should get called, and that model index
>>> custom role should return true.
>> bool filterAcceptsRow(int source_row, const QModelIndex &source_parent)
>> const {
>> QModelIndex index = source_parent.child(source_row, 0);
>> QString path = index.data(QDirModel::FilePathRole).toString();
>> return QFileInfo(path).isFile();
>> }
>
> Hmm, according to your OP this is not the right way, I mean you don't
> want to filter out directories that have subdirs or files. The last line
> shoule be something along this:
>
> if( QFileInfo(path).isFile() )
> return true;
> else {
> return QDir(path).entryList( QStringList() << "*" ).isEmpty();
> }
>
> Which first checks for file/dir (not on non-windows platforms there are
> elements that are neither files nor dirs, so you might also want to
> check for symlinks). If its a dir it checks wether the dir has any
> children and if so it doesn't filter the dir out.
>
> Andreas
>
Well, in fact I *do* want to filter out directories that have subdirs or
files. The view should just display the files in a certain folder, but
no sub-folders. Problem seems to be that if folders are filtered out,
the view can't reach the files.
Btw, I just used the QDirModel as a simple sample, so at least the
platform issues you mentioned don't matter :)
M
--
[ signature omitted ]
Message 10 in thread
> >> bool filterAcceptsRow(int source_row, const QModelIndex
&source_parent)
> >> const {
> >> QModelIndex index = source_parent.child(source_row, 0);
> >> QString path = index.data(QDirModel::FilePathRole).toString();
> >> return QFileInfo(path).isFile();
> >> }
Why cant you make that last line QFileInfo(path).isFile() || path ==
rootFolder.
Have your filter model, STORE the root folder to show.
Scott
--
[ signature omitted ]
Message 11 in thread
Scott Aron Bloom wrote:
>>>> bool filterAcceptsRow(int source_row, const QModelIndex
> &source_parent)
>>>> const {
>>>> QModelIndex index = source_parent.child(source_row, 0);
>>>> QString path = index.data(QDirModel::FilePathRole).toString();
>>>> return QFileInfo(path).isFile();
>>>> }
>
> Why cant you make that last line QFileInfo(path).isFile() || path ==
> rootFolder.
>
>
> Have your filter model, STORE the root folder to show.
>
> Scott
>
Ok, this solution works (kind-of). Thanks a lot, everyone.
It would be nice if the filter model would work without having to know
the root index, because this way it is bound to the root index of the
connected view(s) and has to be updated whenever the view's root index
changes.
Also, I get some weird behaviour when connecting two views, each with
separate filter models, to the same base model. I'm not sure if this is
because of the filter, the base model, or the view implementation.
Thanks again :)
Best,
M
--
[ signature omitted ]
Message 12 in thread
> -----Original Message-----
> From: Martin [mailto:martin.umgeher@xxxxxxxxxxx]
> Sent: Thursday, January 25, 2007 5:26 AM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Filtering a composite-based model
>
> Scott Aron Bloom wrote:
> >>>> bool filterAcceptsRow(int source_row, const QModelIndex
> > &source_parent)
> >>>> const {
> >>>> QModelIndex index = source_parent.child(source_row, 0);
> >>>> QString path = index.data(QDirModel::FilePathRole).toString();
> >>>> return QFileInfo(path).isFile();
> >>>> }
> >
> > Why cant you make that last line QFileInfo(path).isFile() || path ==
> > rootFolder.
> >
> >
> > Have your filter model, STORE the root folder to show.
> >
> > Scott
> >
>
> Ok, this solution works (kind-of). Thanks a lot, everyone.
>
> It would be nice if the filter model would work without having to know
> the root index, because this way it is bound to the root index of the
> connected view(s) and has to be updated whenever the view's root index
> changes.
The thing to remember, from an abstract modelview architecture point of
view, is any model index can be the root. The filtersort proxy only
filters and sorts based on criteria you set up. For the filtering, it
does not know if the model index sent in is the root or the leaf... All
the model knows is if you showing it or not.
Depending on the source model, you may not have a single root, you could
be looking at a grid, or a list...
I have used the filter proxy as a "Show this root only" where when you
initialized it, you set what root to show.
>
> Also, I get some weird behaviour when connecting two views, each with
> separate filter models, to the same base model. I'm not sure if this
is
> because of the filter, the base model, or the view implementation.
You most likely have something wrong in the base model... With out
defining weird its going to be hard to help here :)
But I have used multiple filters on a single base model, along with a
filter on a filter...
Scott
--
[ signature omitted ]
Message 13 in thread
Scott Aron Bloom wrote:
>> Also, I get some weird behaviour when connecting two views, each with
>> separate filter models, to the same base model. I'm not sure if this
> is
>> because of the filter, the base model, or the view implementation.
>
> You most likely have something wrong in the base model... With out
> defining weird its going to be hard to help here :)
Took me some time, but I came up with a simple sample demonstrating the
problem. I think it's a bug, but still it would be nice if you had a
look and commented.
Scenario: The model is a tree model with two kinds of nodes, containers
and leafs. I demo-implemented this using a QStandardItemModel, the item
text representing the node type ("L" is for leaf). The filter model is
implemented as discussed in this thread (the filter works by checking
the text data of the index; if it's "L", it's a leaf). For the demo, I
constructed a tree with two main branches:
+-C1
+-C11
+-L
+-C2
+-L
The UI shows two filtered table views (one for C1, one for C2), and a
tree view showing the whole tree (not filtered, just for checking).
Initially, this works: both tables only show "L"s, the container node
C11 is filtered out.
Now comes the tricky part: when a new leaf node is inserted in C1, all
views get updated. The table view of C1 shows one more leaf (and still
filters out C11, good), the tree view shows another L as child node of
C1, but the table view of C2 shows.... C2. Yes, no more L in there, it
shows the container node itself. This only happens when using the
filter, so either the custom filter or the standard item view code is
buggy...
Here's some demo code:
(1)The filter:
class LeafFilterModel : public QSortFilterProxyModel {
Q_OBJECT
public:
LeafFilterModel(QObject* parent) : QSortFilterProxyModel(parent) { }
void setRoot(const QModelIndex& index) { rootIndex = index; }
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent)
const {
QModelIndex childIndex = sourceModel()->index(sourceRow, 0,
sourceParent);
return (childIndex == rootIndex) || (childIndex.data().toString() ==
"L");
}
private:
QPersistentModelIndex rootIndex;
};
(2)A main window setting everything up:
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = 0) : QMainWindow(parent) {
// create model
model = new QStandardItemModel(this);
container1 = new QStandardItem("C1");
container2 = new QStandardItem("C2");
model->invisibleRootItem()->appendRow(container1);
model->invisibleRootItem()->appendRow(container2);
container1->appendRow(new QStandardItem("C11"));
container1->appendRow(new QStandardItem("L"));
container2->appendRow(new QStandardItem("L"));
// create UI
QWorkspace* workspace = new QWorkspace;
setCentralWidget(workspace);
workspace->addWindow(createFilteredTable(model->index(0, 0)));
workspace->addWindow(createFilteredTable(model->index(1, 0)));
QTreeView* tree = new QTreeView;
tree->setModel(model);
workspace->addWindow(tree);
addToolBar("Yo")->addAction("foo", this, SLOT(foo()));
}
private slots:
void foo() {
container1->appendRow(new QStandardItem("L"));
}
private:
QStandardItemModel* model;
QStandardItem *container1;
QStandardItem *container2;
QWidget* createFilteredTable(const QModelIndex& rootIndex) {
LeafFilterModel* filter = new LeafFilterModel(this);
filter->setSourceModel(model);
filter->setRoot(rootIndex);
QTableView* table = new QTableView;
table->setModel(filter);
table->setRootIndex(filter->mapFromSource(rootIndex));
return table;
}
};
(3)... and a little main:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
return a.exec();
}
That's it. Would be grat if someone could try this out. It really smells
buggy to me...
Thanks for reading this looooong post :)
Best,
M
--
[ signature omitted ]