Exclude QFileSystemModel.setNameFilters

622 views
Skip to first unread message

Ruchit Bhatt

unread,
Nov 8, 2016, 12:56:20 AM11/8/16
to Python Programming for Autodesk Maya
Hi,
if i run below lines, QFileSystemModel will keep files with extension xml,txt & mel.
But i want invert of this..(i.e i want to remove xml, txt & mel from QFileSystemModel)
So tell me how to do this ??

self.dirModel.setNameFilters(['*.xml', '*.txt', '*.mel'])
self.dirModel.setNameFilterDisables(False)





Justin Israel

unread,
Nov 8, 2016, 5:09:37 AM11/8/16
to python_in...@googlegroups.com
Because the QFileSystemModel only lets you specify wildcard patterns to match, you don't have a lot of flexibility with just that model. But if you use a QSortFilterProxyModel then you can apply any kind of transformations you want on the source model, before the view sees it.

I've put together an example for you:

The proxy model is really basic, but you can see how it can be expanded to do whatever kind of filtering options you want. I've just got it ignoring rows where the basename ends in a particular extension.

Justin
 



--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/f2730d5e-9cdf-4041-b9dd-8c2bfa984efd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Marcus Ottosson

unread,
Nov 8, 2016, 5:22:31 AM11/8/16
to python_in...@googlegroups.com

Great example, Justin.

I was about to post this, which is a more complex example.

>>> proxy = ProxyModel(original_model)
>>> proxy.add_exclusion("hasCompatible", False)

Where hasCompatible is a “role” and False is the value of this role used to determine whether or not to exclude it.

It also does inclusion, as in, only matching items are included. Combined they enable excluding within a subset of included items.

>>> proxy.add_inclusion("itemType", "plugin")

It’s used like this.

Include

Exclude

Hope it helps!

Ruchit Bhatt

unread,
Nov 8, 2016, 9:05:59 AM11/8/16
to Python Programming for Autodesk Maya



thnx for reply, will chck your code and here is snapshot of UI. On click to export button all files in treeview will be pack in *.tar file.

Ruchit Bhatt

unread,
Dec 1, 2016, 2:19:35 AM12/1/16
to Python Programming for Autodesk Maya
@Marcus...Tell me, below code is going in right direction or not ??
Thank you

class customProxyModel(QtGui.QSortFilterProxyModel):
def __init__(self, parent=None):
super(customProxyModel, self).__init__(parent)
self._includes = {'fileName':[], 'fileType':[], 'fileSize':[], 'fileDate':[]}
self._excludes = {'fileName':[], 'fileType':[], 'fileSize':[], 'fileDate':[]}

def add_exclusion(self, role, value):
self._add_rule(self._excludes, role, value)
def remove_exclusion(self, role, value=None):
self._remove_rule(self._excludes, role, value)
def set_exclusion(self, rules):
self._set_rules(self._excludes, rules)
def clear_exclusion(self):
self._clear_group(self._excludes)

def add_inclusion(self, role, value):
self._add_rule(self._includes, role, value)
def add_inclusion(self, role, value):
self._remove_rule(self._includes, role, value)
def set_inclusion(self, rules):
self._set_rules(self._includes, rules)
def clear_inclusion(self):
self._clear_group(self._includes)

def _add_rule(self, group, role, value):
group[role].append(value)
self.invalidate()
def _remove_rule(self, group, role, value):
group[role].remove(value)
self.invalidate()
def _set_rules(self, group, rules):
group.clear()
for rule in rules:
self._add_rule(group, *rule)
self.invalidate()
def _clear_group(self, group):
group.clear()
self.invalidate()

def filterAcceptsRow(self, srcRow, srcParent):
idx = self.sourceModel().index(srcRow, 0, srcParent)
filePath = self.sourceModel().filePath(idx)
fileDate = self.sourceModel().fileInfo(idx).lastModified()
fileSize = self.sourceModel().fileInfo(idx).size()
fileLongName = idx.data()

for exc in self._excludes:
if fileLongName.endswith(exc):
return False

for fileKey, fileValue in self._excludes.items():
for value in fileValue:
if fileKey == 'fileName':
if fileLongName.endswith(fileLongName.endswith(value)):
return False
elif fileKey == 'fileType':
if fileLongName.endswith(fileLongName.endswith(value)):
return False
elif fileKey == 'fileSize':
if fileLongName.endswith(fileLongName.endswith(value)):
return False
elif fileKey == 'fileDate':
if fileLongName.endswith(fileLongName.endswith(value)):
return False


for fileKey, fileValue in self._includes.items():
for value in fileValue:
if fileKey == 'fileName':
if fileLongName.endswith(fileLongName.endswith(value)):
return True
elif fileKey == 'fileType':
if fileLongName.endswith(fileLongName.endswith(value)):
return True
elif fileKey == 'fileSize':
if fileLongName.endswith(fileLongName.endswith(value)):
return True
elif fileKey == 'fileDate':
if fileLongName.endswith(fileLongName.endswith(value)):
return True
return True

 

Ruchit Bhatt

unread,
Dec 2, 2016, 1:01:23 AM12/2/16
to Python Programming for Autodesk Maya
@Justin 

Instead of 
name = idx.data()

for exc in self._excludes:
   
if name.endswith(exc):
       
return False

Below one is simple & perfect in my case, wht do you think ??
fileType = self.sourceModel().fileInfo(idx).suffix()
for exc in self._excludes:
   
if exc == fileType:
        return False


Justin Israel

unread,
Dec 2, 2016, 3:22:01 AM12/2/16
to Python Programming for Autodesk Maya

Sure you can do it like that. It will work fine for testing extensions in 99% of the cases. The 1% edge case is where you for some reason ever put another proxy model in between this one and the source model and this code breaks because you are depending on the source model being a specific derived type with a method fileInfo().


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Alok Gandhi

unread,
Dec 2, 2016, 3:42:27 AM12/2/16
to python_in...@googlegroups.com
Might I also suggest more pythonic and performant code:
fileType = self.sourceModel().fileInfo(idx).suffix()
return fileType not in self._excludes

On Fri, Dec 2, 2016 at 4:21 PM, Justin Israel <justin...@gmail.com> wrote:

Sure you can do it like that. It will work fine for testing extensions in 99% of the cases. The 1% edge case is where you for some reason ever put another proxy model in between this one and the source model and this code breaks because you are depending on the source model being a specific derived type with a method fileInfo().


On Fri, Dec 2, 2016, 7:01 PM Ruchit Bhatt <ruchitinn...@gmail.com> wrote:
@Justin 

Instead of 
name = idx.data()

for exc in self._excludes:
   
if name.endswith(exc):
       
return False

Below one is simple & perfect in my case, wht do you think ??
fileType = self.sourceModel().fileInfo(idx).suffix()
for exc in self._excludes:
   
if exc == fileType:
        return False


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA1F_ghRk9txA8gtSjyZ-6jaVdkjuggCjDQrEin2iOVKiw%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--

Marcus Ottosson

unread,
Dec 2, 2016, 4:13:21 AM12/2/16
to python_in...@googlegroups.com

An alternative to fetching the object and accessing properties of this object, you could use the “role” functionality of the model.

return idx.data(FileTypeRole) not in self._excludes

Each index carries a method called data which is shorthand for model.data(index, role). In this case, this would call data on the proxy model, where you either forward it to the original model, or handle it explicitly.

FileTypeRole = QtCore.Qt.UserRole + 1

def data(self, index, role):
   if role == FileTypeRole:
      return ".ma"

The benefit being that you avoid the trap Justin mentioned of some day switching out the underlying object, or wanting to use the same proxy in other programs where exact objects differ. In this case, you may redirect differences in the model.


On 2 December 2016 at 08:42, Alok Gandhi <alok.ga...@gmail.com> wrote:
Might I also suggest more pythonic and performant code:
fileType = self.sourceModel().fileInfo(idx).suffix()
return fileType not in self._excludes
On Fri, Dec 2, 2016 at 4:21 PM, Justin Israel <justin...@gmail.com> wrote:

Sure you can do it like that. It will work fine for testing extensions in 99% of the cases. The 1% edge case is where you for some reason ever put another proxy model in between this one and the source model and this code breaks because you are depending on the source model being a specific derived type with a method fileInfo().


On Fri, Dec 2, 2016, 7:01 PM Ruchit Bhatt <ruchitinn...@gmail.com> wrote:
@Justin 

Instead of 
name = idx.data()

for exc in self._excludes:
   
if name.endswith(exc):
       
return False

Below one is simple & perfect in my case, wht do you think ??
fileType = self.sourceModel().fileInfo(idx).suffix()
for exc in self._excludes:
   
if exc == fileType:
        return False


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.



--

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Ruchit Bhatt

unread,
Dec 5, 2016, 9:05:35 PM12/5/16
to Python Programming for Autodesk Maya
@Marcus & Justin
Thnx for help, filter part is working fine now .
Need help for one more thing, how to get list of all files recursively after filter done??

i tried rowCount method with proxy class but nothing works ??
 

Justin Israel

unread,
Dec 6, 2016, 12:18:49 AM12/6/16
to python_in...@googlegroups.com
Why doesn't rowCount work for you? When I call rowCount() on the proxy model, I get a value of 1. Then when I recursively use that as the parent to rowCount(parent), I can continue recursing through the children of the model. Does this not work the same for you?


 
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/98c937f3-4cac-463e-a62e-bb37999e5d72%40googlegroups.com.

Ruchit Bhatt

unread,
Dec 6, 2016, 2:31:31 AM12/6/16
to Python Programming for Autodesk Maya
I tried 
   
print self.proxyModel.rowCount()  #works fine but its not  recursive

and
   
 print self.proxyModel.rowCount(parent=QtCore.QModelIndex())    #Gives error


how you are able to use parent outside class ??

Justin Israel

unread,
Dec 6, 2016, 5:09:33 AM12/6/16
to python_in...@googlegroups.com
On Tue, Dec 6, 2016 at 8:31 PM Ruchit Bhatt <ruchitinn...@gmail.com> wrote:
I tried 
   
print self.proxyModel.rowCount()  #works fine but its not  recursive


I'm not sure what you expect the results to be. What kind of recursive value do you expect? A total of all row count of all hierarchies in the tree?
Model.rowCount() gives you the row count of the root of the model, which if you are getting 1 means an invisible root item. 

If you wanted to print the first tier of visible items, it would be something like this:

model = tree.model()
root = model.index(0,0)
for row in xrange(model.rowCount(root)):
    print model.index(row, 0, root).data()

Now, if you were to do this recursively or iteratively, then you could print every row, down every child, until you decide to stop. Is that what you are after? A recursive or iterative solution to walking the tree model? 
 
and
   
 print self.proxyModel.rowCount(parent=QtCore.QModelIndex())    #Gives error


The parent argument would be an index that you get from the model in the first place. Like in my previous example, you could start with the invisible root item of the tree:

root = model.index(0,0)

Now you can pass this parent in order to get the row count of it, and then continue to change the parent and either do depth first or breadth first traversal through the tree model.
 

how you are able to use parent outside class ??

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Justin Israel

unread,
Dec 6, 2016, 5:14:23 AM12/6/16
to python_in...@googlegroups.com
On Tue, Dec 6, 2016 at 11:09 PM Justin Israel <justin...@gmail.com> wrote:
On Tue, Dec 6, 2016 at 8:31 PM Ruchit Bhatt <ruchitinn...@gmail.com> wrote:
I tried 
   
print self.proxyModel.rowCount()  #works fine but its not  recursive


I'm not sure what you expect the results to be. What kind of recursive value do you expect? A total of all row count of all hierarchies in the tree?
Model.rowCount() gives you the row count of the root of the model, which if you are getting 1 means an invisible root item. 

If you wanted to print the first tier of visible items, it would be something like this:

model = tree.model()
root = model.index(0,0)
for row in xrange(model.rowCount(root)):
    print model.index(row, 0, root).data()


Note, another way you can express this is also using the child() method of a particular index:

for row in xrange(model.rowCount(root)):
    print root.child(row, 0).data()

And also to clarify, when I am talking about the invisible root item, I am referring to the path which was passed to QFileSystemModel.setRootPath()
It is being hidden from the view, but it ends up being the top level item when you query the model generically. 

Ruchit Bhatt

unread,
Dec 6, 2016, 7:49:34 AM12/6/16
to Python Programming for Autodesk Maya
Basically i am looking for list of files with their path,

    def fileListFn(self, srcRow, srcParent):

        idx
= self.sourceModel().index(srcRow, 0, srcParent)
        filePath
= self.sourceModel().filePath(idx)

       
if os.path.isfile(filePath):
           
print filePath

Issue with above function is,
it returns same value multiple times and to print  all files you will need to expand all

Justin Israel

unread,
Dec 6, 2016, 4:20:33 PM12/6/16
to python_in...@googlegroups.com
Do you have an example of where you are trying to use this function within your code? This function on its own seems technically sound. But how you are trying to use it could be problematic. 

It is true that if your goal is to get all the paths from a given point in the model, recursively, that the model may not have that data loaded because it uses a lazy loading approach with canFetchMore() and fetchMore() on demand. So it would mean that as you are walking the model you would have to either expand the tree in the view beforehand, or directly use fetchMore() on the index before looping over its children. This will make the file model scan the directory and populate the children. 
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages