5653310f5ea976a13bb9e4b313d6100cc42ccac6
[jamaendo] / jamaui / albumlist.py
1 import os
2 import gtk
3 import gobject
4 import hildon
5 import jamaendo
6 import util
7 from settings import settings
8 from postoffice import postoffice
9 import logging
10
11 log = logging.getLogger(__name__)
12
13 class _BaseList(gtk.TreeView):
14     """
15     TODO: unify the different lists into one
16     """
17     ICON_SIZE = 50
18
19     def __init__(self):
20         gtk.TreeView.__init__(self)
21         self.__store = None
22         self.default_pixbuf = util.find_resource('album.png')
23         self.connect('destroy', self.on_destroy)
24
25     def get_pixbuf(self, img):
26         try:
27             return gtk.gdk.pixbuf_new_from_file_at_size(img,
28                                                         self.ICON_SIZE,
29                                                         self.ICON_SIZE)
30         except gobject.GError:
31             log.error("Broken image in cache: %s", img)
32             try:
33                 os.unlink(img)
34             except OSError, e:
35                 log.warning("Failed to unlink broken image.")
36             if img != self.default_pixbuf:
37                 return self.get_default_pixbuf()
38             else:
39                 return None
40
41     def get_default_pixbuf(self):
42         if self.default_pixbuf:
43             return self.get_pixbuf(self.default_pixbuf)
44
45     def on_destroy(self, wnd):
46         pass
47
48 class MusicList(_BaseList):
49     def __init__(self):
50         _BaseList.__init__(self)
51         (self.COL_ICON, self.COL_NAME, self.COL_ID, self.COL_IMAGE) = range(4)
52         self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, int, str)
53
54         self.set_model(self.__store)
55
56         icon = gtk.TreeViewColumn('Icon')
57         self.append_column(icon)
58         cell = gtk.CellRendererPixbuf()
59         icon.pack_start(cell, True)
60         icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
61
62         col = gtk.TreeViewColumn('Name')
63         self.append_column(col)
64         cell = gtk.CellRendererText()
65         col.pack_start(cell, True)
66         col.add_attribute(cell, 'text', self.COL_NAME)
67         self.set_search_column(self.COL_NAME)
68         col.set_sort_column_id(self.COL_NAME)
69
70         postoffice.connect('images', self, self.on_images)
71
72     def get_item_id(self, path):
73         return self.__store.get(self.__store.get_iter(path), self.COL_ID)[0]
74
75     def on_destroy(self, wnd):
76         postoffice.disconnect('images', self)
77
78     def on_images(self, images):
79         for url, image in images:
80             for row in self.__store:
81                 if row[self.COL_IMAGE] == url:
82                     pb = self.get_pixbuf(image)
83                     if pb:
84                         row[self.COL_ICON] = pb
85
86     def add_items(self, items):
87         images = [x for x in (self.get_item_image(item) for item in items) if x]
88         for item in items:
89             txt = self.get_item_text(item)
90             self.__store.append([self.get_default_pixbuf(), txt, item.ID, self.get_item_image(item)])
91         if images:
92             postoffice.notify('request-images', images)
93
94     def get_item_text(self, item):
95         if isinstance(item, jamaendo.Album):
96             return "%s - %s" % (item.artist_name, item.name)
97         elif isinstance(item, jamaendo.Track):
98             return "%s - %s" % (item.artist_name, item.name)
99         else:
100             return item.name
101
102     def get_item_image(self, item):
103         ret = None
104         if isinstance(item, jamaendo.Track):
105             ret = item.album_image
106         elif hasattr(item, 'image'):
107             ret = item.image
108         if ret:
109             ret = ret.replace('1.100.jpg', '1.%d.jpg'%(self.ICON_SIZE))
110         return ret
111
112 class AlbumList(_BaseList):
113     def __init__(self):
114         _BaseList.__init__(self)
115         (self.COL_ICON, self.COL_NAME, self.COL_ID) = range(3)
116         self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, int)
117         self.__show_artist = True
118
119         self.set_model(self.__store)
120
121         icon = gtk.TreeViewColumn('Icon')
122         self.append_column(icon)
123         cell = gtk.CellRendererPixbuf()
124         icon.pack_start(cell, True)
125         icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
126
127         col = gtk.TreeViewColumn('Name')
128         self.append_column(col)
129         cell = gtk.CellRendererText()
130         col.pack_start(cell, True)
131         col.add_attribute(cell, 'text', self.COL_NAME)
132         self.set_search_column(self.COL_NAME)
133         col.set_sort_column_id(self.COL_NAME)
134
135         postoffice.connect('album-cover', self, self.on_album_cover)
136
137     def on_destroy(self, wnd):
138         _BaseList.on_destroy(self, wnd)
139         postoffice.disconnect('album-cover', self)
140
141     def on_album_cover(self, albumid, size, cover):
142         if size == self.ICON_SIZE:
143             for row in self.__store:
144                 if row[self.COL_ID] == albumid:
145                     row[self.COL_ICON] = self.get_pixbuf(cover)
146
147     def add_album(self, album):
148         if self.__show_artist:
149             txt = "%s - %s" % (album.artist_name, album.name)
150         else:
151             txt = album.name
152         self.__store.append([self.get_default_pixbuf(), txt, album.ID])
153         postoffice.notify('request-album-cover', album.ID, self.ICON_SIZE)
154
155     def get_album_id(self, path):
156         return self.__store.get(self.__store.get_iter(path), self.COL_ID)[0]
157
158     def show_artist(self, show):
159         self.__show_artist = show
160
161 class TrackList(_BaseList):
162     def __init__(self, numbers = True):
163         _BaseList.__init__(self)
164         self.track_numbers = numbers
165         self.__store = gtk.ListStore(int, str, int)
166         self.set_model(self.__store)
167
168         if numbers:
169             col0 = gtk.TreeViewColumn('Num')
170             self.append_column(col0)
171             cell0 = gtk.CellRendererText()
172             col0.pack_start(cell0, True)
173             col0.add_attribute(cell0, 'text', 0)
174
175         col = gtk.TreeViewColumn('Name')
176         self.append_column(col)
177         cell = gtk.CellRendererText()
178         col.pack_start(cell, True)
179         col.add_attribute(cell, 'text', 1)
180
181         self.set_search_column(1 if numbers else 0)
182         col.set_sort_column_id(0)
183
184     def add_track(self, track):
185         self.__store.append([track.numalbum, track.name, track.ID])
186
187     def get_track_id(self, path):
188         treeiter = self.__store.get_iter(path)
189         _, _, _id = self.__store.get(treeiter, 0, 1, 2)
190         return _id
191
192 class RadioList(_BaseList):
193     def __init__(self):
194         _BaseList.__init__(self)
195         (self.COL_ICON, self.COL_NAME, self.COL_ID, self.COL_IMAGE) = range(4)
196         self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, int, str)
197         self.set_model(self.__store)
198
199         icon = gtk.TreeViewColumn('Icon')
200         self.append_column(icon)
201         cell = gtk.CellRendererPixbuf()
202         icon.pack_start(cell, True)
203         icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
204
205         col = gtk.TreeViewColumn('Name')
206         self.append_column(col)
207         cell = gtk.CellRendererText()
208         col.pack_start(cell, True)
209         col.add_attribute(cell, 'text', self.COL_NAME)
210         self.set_search_column(self.COL_NAME)
211         col.set_sort_column_id(self.COL_NAME)
212
213         postoffice.connect('images', self, self.on_images)
214
215     def on_destroy(self, wnd):
216         postoffice.disconnect('images', self)
217
218     def add_radios(self, radios):
219         for radio in radios:
220             self.__store.append([self.get_default_pixbuf(), self.radio_name(radio), radio.ID, radio.image])
221         postoffice.notify('request-images', [radio.image for radio in radios])
222
223
224     def get_radio_id(self, path):
225         treeiter = self.__store.get_iter(path)
226         name, _id = self.__store.get(treeiter, self.COL_NAME, self.COL_ID)
227         return name, _id
228
229     def on_images(self, images):
230         for url, image in images:
231             for row in self.__store:
232                 if row[self.COL_IMAGE] == url:
233                     pb = self.get_pixbuf(image)
234                     if pb:
235                         row[self.COL_ICON] = pb
236
237     def radio_name(self, radio):
238         if radio.idstr:
239             return radio.idstr.capitalize()
240         elif radio.name:
241             return radio.name
242         else:
243             return "Radio #%s" % (radio.ID)