It is not possible to create a recursive function over a pyGTK treeStore
Bruno Desthuilliers
bruno.42.desthuilliers at wtf.websiteburo.oops.com
Fri Jun 29 08:53:08 EDT 2007
sebastien.abeille at gmail.com 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)
</side-note>
> 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[i]
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[i]):
> print path+'/'+files[i]+" is a file"
> treeStoreNode.append( None, (path+'/'+files[i], 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[i]):
Note that you should'nt do this test if the previous succeeded, since
both are exclusive. IOW, use a elif.
> print path+'/'+files[i]+" is a directory"
> mother = self.tree_store.append(None, (path+'/'+files[i], 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[i], 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
More information about the Python-list
mailing list