It is not possible to create a recursive function over a pyGTK treeStore

S

sebastien.abeille

Hello,

I would like to create a minimalist file browser using pyGTK.

Having read lot of tutorials, it seems to me that that in my case, the
best solution is
to have a gtk.TreeStore containing all the files and folders so that
it would map the
file system hierarchy.

I wrote a recursive function that would go through the file system
tree.

My problem is that a sub-node of a gtk.TreeStore is not a
gtk.TreeStore, but
a gtk.TreeIter. And gtk.treeter has almost no functions I would be
able to use (like "append")
Therefore I can not explore the whole file system.

Do you have another way so that I would be able to put all the file
system hierarchy
into a gtk.TreeStore?
I was quite happy with my recursive solution ...



===================================
code :
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, gobject, os


prefdir="/tmp/a"

class InfoModele:

def matchPathTreetoModelTree(self, path, treeStoreNode):
files = [f for f in os.listdir(path) if f[0] <> '.']
for i in range(len(files)):
if os.path.isfile(path+'/'+files):
print path+'/'+files+" is a file"
treeStoreNode.append( None, (path+'/'+files, None) )
if os.path.isdir(path+'/'+files): #is a directory, go
recursively
print path+'/'+files+" is a directory"
mother = self.tree_store.append( None, (path+'/'+files, None) )
self.matchPathTreetoModelTree(path+'/'+files, mother)

def __init__(self):
self.tree_store = gtk.TreeStore( gobject.TYPE_STRING,
gobject.TYPE_STRING)
path=prefdir
self.matchPathTreetoModelTree(prefdir, self.tree_store)

if __name__ == "__main__":
i=InfoModele()

=================================
file system :
a
|-ab/
|-abc/
|-abcd

================================
Program output :
/tmp/a/ab is a directory
/tmp/a/ab/abc is a file
Traceback (most recent call last):
File "question.py", line 28, in <module>
i=InfoModele()
File "question.py", line 25, in __init__
self.matchPathTreetoModelTree(prefdir, self.tree_store)
File "question.py", line 20, in matchPathTreetoModelTree
self.matchPathTreetoModelTree(path+'/'+files, mother)
File "question.py", line 16, in matchPathTreetoModelTree
treeStoreNode.append( None, (path+'/'+files, None) )
AttributeError: 'gtk.TreeIter' object has no attribute 'append'
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
Hello,

I would like to create a minimalist file browser using pyGTK.

Having read lot of tutorials, it seems to me that that in my case, the
best solution is
to have a gtk.TreeStore containing all the files and folders so that
it would map the
file system hierarchy.

I wrote a recursive function that would go through the file system
tree.

My problem is that a sub-node of a gtk.TreeStore is not a
gtk.TreeStore, but
a gtk.TreeIter. And gtk.treeter has almost no functions I would be
able to use (like "append")
Therefore I can not explore the whole file system.

Do you have another way so that I would be able to put all the file
system hierarchy
into a gtk.TreeStore?

Sorry, no anwser to that - I don't do much GUI programming. But asking
on GTK mailing-list may be a good idea.
I was quite happy with my recursive solution ...

A couple of comments on the code:
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, gobject, os


prefdir="/tmp/a"

class InfoModele:

Do yourself (and the world) a favour: use new-styles classes. And while
we're at it, be consistant wrt/ naming:

class InfoModel(object):
def matchPathTreetoModelTree(self, path, treeStoreNode):

<side-note>
You're of course free to use mixedCase, but unless this is a
project-specific (or workplace-specific) convention, it might be better
to stick to pep08 (all_lower_with_underscores). But if you choose
mixedCase, at least be consistant
(ie : self.tree_store => self.treeStore)
files = [f for f in os.listdir(path) if f[0] <> '.']

could also use str.startswith here:

files = [f for f in os.listdir(path) \
if not f.startswith('.')]

But I don't see the point of this listcomp when you could filter out
special names in the for loop.
for i in range(len(files)):

Coming from a C-like language ?-)

The for loop in Python is much smarter than this. You don't have to use
an explicit indexing, you can just iterate over the sequence, ie,
instead of:

for i in range(len(files)):
the_file = files
do_something_with(the_file)

You can do:

for the_file in files:
do_something_with(the_file)

NB : if you need the index for any other reason, you can use enumerate(seq):

for i, the_file in enumerate(files):
print >> sys.stderr, "file #%s" % i
do_something_with(the_file)

if os.path.isfile(path+'/'+files):
print path+'/'+files+" is a file"
treeStoreNode.append( None, (path+'/'+files, None) )


My...

1/: use os.path.join()
2/: avoid recomputing the same value thrice or more, especially if
within a loop
3/ (optional, but good to know): within loops, make the often used
methods locals - this will save *a lot* of lookup time (since Python is
highly dynamic, the compiler cannot optimize much here).
4/ stdout is for normal program outputs. Error messages, debug
informations et al should go to stderr
if os.path.isdir(path+'/'+files):


Note that you should'nt do this test if the previous succeeded, since
both are exclusive. IOW, use a elif.
> print path+'/'+files+" is a directory"
> mother = self.tree_store.append(None, (path+'/'+files, None))


You certainly have an error here. If you're already in a subdirectory,
you don't want to create the node on the root but on the parent's
directory node - IOW, dont use self.tree_store, but treeStoreNode. Which
allow to further simplify the code (cf below)
> self.matchPathTreetoModelTree(path+'/'+files, mother)

def __init__(self):
self.tree_store = gtk.TreeStore( gobject.TYPE_STRING,
gobject.TYPE_STRING)
path=prefdir


This should be an argument of the initializer
self.matchPathTreetoModelTree(prefdir, self.tree_store)
(snip)

Suggestion:

class InfoModel(object):
def __init__(self, path):
self.basepath = path
self.treeStore = gtk.TreeStore(
gobject.TYPE_STRING,
gobject.TYPE_STRING
)
self.matchPathTreetoModelTree(path, self.treeStore)

def matchPathTreetoModelTree(self, path, treeStoreNode):
isdir = os.path.isdir
join = os.path.join
append= treeStoreNode.append
recurse = self.matchPathTreetoModelTree

filenames = os.listdir(path)
for filename in filenames:
if filename.startswith('.'):
continue

filepath = join(path, filename)
# tracing for debug - assuming this will disappear
# before going to prod, it's ok to repeat the call
# to isdir() here
print >> sys.stderr, "%s is a %s" \
% (filepath, ('file', 'dir')[isdir(filepath)])

# nb: you may want to filter out non-regular files
# like devices, sockects etc here
newnode = append(None, (filepath, None))
if isdir(filepath):
recurse(filepath, newnode)


HTH
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top