Work-around GTK bug #523724.
[rox-shell.git] / rox / shell / directory.py
blobc9433fb800955c1100cf4259246560d9f28232da
1 """
2 @copyright: (C) 2008, Thomas Leonard
3 @see: U{http://roscidus.com}
4 """
5 from zeroinstall.support import tasks # tmp
7 import gobject
8 import _gio as gio
9 import gtk
10 import weakref
12 gtk_theme = gtk.icon_theme_get_default()
14 icon_size = 48
16 def get_themed_icon(name, icon_size):
17 try:
18 return gtk_theme.load_icon('text-x-generic', icon_size, 0)
19 except gobject.GError:
20 return None
22 icon_text_plain = get_themed_icon('text-x-generic', icon_size)
23 icon_dir = get_themed_icon('folder', icon_size)
25 def sort_key(name, info):
26 t = 9 - int(info.get_file_type())
27 return str(t) + name.lower()
29 class DirModel:
30 NAME = 0
31 PIXBUF = 1
32 INFO = 2
33 SORT = 3 # Type-then-name
35 model = None
36 monitor = None
38 def __init__(self, file):
39 assert isinstance(file, gio.File), file
40 self.file = file
41 self.users = []
43 def __del__(self):
44 assert not self.users, "DirModel garbage collected while still monitoring! Monitored by " + str(self.users)
46 def add_ref(self, user):
47 user = id(user)
49 if not self.users:
50 # First user...
51 assert not self.monitor
52 assert not self.model
53 self.model = gtk.ListStore(str, gtk.gdk.Pixbuf, object, str)
55 # Should really be the view that sorts, but see GTK bug #523724
56 self.model.set_sort_column_id(DirModel.SORT, gtk.SORT_ASCENDING)
58 self.monitor = self.file.monitor_directory(0)
59 weakself = weakref.ref(self)
60 self.monitor.connect('changed', lambda *args: weakself().contents_changed(*args))
61 self.build_contents()
63 self.users.append(user)
65 def del_ref(self, user):
66 user = id(user)
67 self.users.remove(user)
69 if not self.users:
70 # Last user...
71 self.model.clear()
72 self.model = None
73 self.monitor.cancel()
74 self.monitor = None
76 def contents_changed(self, monitor, dir_file, other_file, event_type):
77 self.build_contents()
79 def build_contents(self):
80 self.model.clear()
81 self.error = None
83 try:
84 e = self.file.enumerate_children('standard::*', 0)
85 except gobject.GError, ex:
86 self.error = ex
87 return
89 if not e:
90 return # Empty dir
92 while True:
93 info = e.next_file()
94 if not info:
95 break
97 name = info.get_name()
98 if not name.startswith('.'):
99 new = self.model.append(None)
100 pixbuf = None
101 icon = info.get_icon()
102 if icon:
103 gtkicon_info = gtk_theme.choose_icon(icon.get_names(), icon_size, 0)
104 if gtkicon_info:
105 gtkicon_info.get_filename()
106 pixbuf = gtkicon_info.load_icon()
108 self.model[new] = [name, pixbuf, info, sort_key(name, info)]
110 dirs = weakref.WeakValueDictionary()
111 def get_dir_model(file):
112 # Might want some caching here...
113 uri = file.get_uri()
114 try:
115 return dirs[uri]
116 except KeyError:
117 dm = DirModel(file)
118 dirs[uri] = dm
119 return dm