7 import helldon as hildon
12 from postoffice import postoffice
15 log = logging.getLogger(__name__)
17 class _BaseList(gtk.TreeView):
19 TODO: unify the different lists into one
24 gtk.TreeView.__init__(self)
26 self.default_pixbuf = util.find_resource('album.png')
27 self.connect('destroy', self.on_destroy)
28 self.connect('expose-event', self.on_treeview_expose_event)
29 self.loading_message = "Loading..."
30 self.empty_message = "Empty."
31 self._is_loading = True
33 def get_pixbuf(self, img):
35 return gtk.gdk.pixbuf_new_from_file_at_size(img,
38 except gobject.GError:
39 log.error("Broken image in cache: %s", img)
43 log.warning("Failed to unlink broken image.")
44 if img != self.default_pixbuf:
45 return self.get_default_pixbuf()
49 def get_default_pixbuf(self):
50 if self.default_pixbuf:
51 return self.get_pixbuf(self.default_pixbuf)
53 def on_destroy(self, wnd):
56 def set_loading(self, loading):
57 self._is_loading = loading
60 def on_treeview_expose_event(self, treeview, event):
61 if event.window == treeview.get_bin_window():
62 model = treeview.get_model()
63 if (model is not None and model.get_iter_first() is not None):
66 ctx = event.window.cairo_create()
67 ctx.rectangle(event.area.x, event.area.y,
68 event.area.width, event.area.height)
70 x, y, width, height, depth = event.window.get_geometry()
73 text = self.loading_message
75 text = self.empty_message
77 desc = colors.get_font_desc('LargeSystemFont')
78 draw.text_box_centered(ctx, treeview, width, height, text, desc)
82 class MusicList(_BaseList):
84 _BaseList.__init__(self)
85 (self.COL_ICON, self.COL_NAME, self.COL_ID, self.COL_IMAGE) = range(4)
86 self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, int, str)
88 self.set_model(self.__store)
90 icon = gtk.TreeViewColumn('Icon')
91 self.append_column(icon)
92 cell = gtk.CellRendererPixbuf()
93 icon.pack_start(cell, True)
94 icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
96 col = gtk.TreeViewColumn('Name')
97 self.append_column(col)
98 cell = gtk.CellRendererText()
99 col.pack_start(cell, True)
100 col.add_attribute(cell, 'text', self.COL_NAME)
101 self.set_search_column(self.COL_NAME)
102 col.set_sort_column_id(self.COL_NAME)
104 postoffice.connect('images', self, self.on_images)
106 def get_item_id(self, path):
107 return self.__store.get(self.__store.get_iter(path), self.COL_ID)[0]
109 def on_destroy(self, wnd):
110 postoffice.disconnect('images', self)
112 def on_images(self, images):
113 for url, image in images:
114 for row in self.__store:
115 if row[self.COL_IMAGE] == url:
116 pb = self.get_pixbuf(image)
118 row[self.COL_ICON] = pb
120 def add_items(self, items):
121 images = [x for x in (self.get_item_image(item) for item in items) if x]
123 txt = self.get_item_text(item)
124 self.__store.append([self.get_default_pixbuf(), txt, item.ID, self.get_item_image(item)])
126 postoffice.notify('request-images', images)
128 def get_item_text(self, item):
129 if isinstance(item, jamaendo.Album):
130 return "%s - %s" % (item.artist_name, item.name)
131 elif isinstance(item, jamaendo.Track):
132 return "%s - %s" % (item.artist_name, item.name)
136 def get_item_image(self, item):
138 if isinstance(item, jamaendo.Track):
139 ret = item.album_image
140 elif hasattr(item, 'image'):
143 ret = ret.replace('1.100.jpg', '1.%d.jpg'%(self.ICON_SIZE))
146 class AlbumList(_BaseList):
148 _BaseList.__init__(self)
149 (self.COL_ICON, self.COL_NAME, self.COL_ID) = range(3)
150 self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, int)
151 self.__show_artist = True
153 self.set_model(self.__store)
155 icon = gtk.TreeViewColumn('Icon')
156 self.append_column(icon)
157 cell = gtk.CellRendererPixbuf()
158 icon.pack_start(cell, True)
159 icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
161 col = gtk.TreeViewColumn('Name')
162 self.append_column(col)
163 cell = gtk.CellRendererText()
164 col.pack_start(cell, True)
165 col.add_attribute(cell, 'text', self.COL_NAME)
166 self.set_search_column(self.COL_NAME)
167 col.set_sort_column_id(self.COL_NAME)
169 postoffice.connect('album-cover', self, self.on_album_cover)
171 def on_destroy(self, wnd):
172 _BaseList.on_destroy(self, wnd)
173 postoffice.disconnect('album-cover', self)
175 def on_album_cover(self, albumid, size, cover):
176 if size == self.ICON_SIZE:
177 for row in self.__store:
178 if row[self.COL_ID] == albumid:
179 row[self.COL_ICON] = self.get_pixbuf(cover)
181 def add_album(self, album):
182 if self.__show_artist:
183 txt = "%s - %s" % (album.artist_name, album.name)
186 self.__store.append([self.get_default_pixbuf(), txt, album.ID])
187 postoffice.notify('request-album-cover', album.ID, self.ICON_SIZE)
189 def get_album_id(self, path):
190 return self.__store.get(self.__store.get_iter(path), self.COL_ID)[0]
192 def show_artist(self, show):
193 self.__show_artist = show
195 class TrackList(_BaseList):
196 def __init__(self, numbers = True):
197 _BaseList.__init__(self)
198 self.track_numbers = numbers
199 self.__store = gtk.ListStore(int, str, int)
200 self.set_model(self.__store)
203 col0 = gtk.TreeViewColumn('Num')
204 self.append_column(col0)
205 cell0 = gtk.CellRendererText()
206 col0.pack_start(cell0, True)
207 col0.add_attribute(cell0, 'text', 0)
209 col = gtk.TreeViewColumn('Name')
210 self.append_column(col)
211 cell = gtk.CellRendererText()
212 col.pack_start(cell, True)
213 col.add_attribute(cell, 'text', 1)
215 self.set_search_column(1 if numbers else 0)
216 col.set_sort_column_id(0)
218 def add_track(self, track):
219 self.__store.append([track.numalbum, track.name, track.ID])
221 def get_track_id(self, path):
222 treeiter = self.__store.get_iter(path)
223 _, _, _id = self.__store.get(treeiter, 0, 1, 2)
227 class PlaylistList(_BaseList):
229 _BaseList.__init__(self)
230 (self.COL_ICON, self.COL_NAME, self.COL_INFO, self.COL_ID) = range(4)
231 self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, int)
233 self.set_model(self.__store)
235 icon = gtk.TreeViewColumn('Icon')
236 self.append_column(icon)
237 cell = gtk.CellRendererPixbuf()
238 icon.pack_start(cell, True)
239 icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
241 col = gtk.TreeViewColumn('Name')
242 self.append_column(col)
243 cell = gtk.CellRendererText()
244 col.pack_start(cell, True)
245 col.add_attribute(cell, 'text', self.COL_NAME)
247 col = gtk.TreeViewColumn('Info')
248 self.append_column(col)
249 cell = gtk.CellRendererText()
250 cell.set_property('xalign', 1.0)
251 col.pack_start(cell, True)
252 col.add_attribute(cell, 'text', self.COL_INFO)
254 self.set_search_column(self.COL_NAME)
255 col.set_sort_column_id(self.COL_NAME)
257 postoffice.connect('album-cover', self, self.on_album_cover)
259 def on_destroy(self, wnd):
260 _BaseList.on_destroy(self, wnd)
261 postoffice.disconnect('album-cover', self)
263 def on_album_cover(self, albumid, size, cover):
264 if size == self.ICON_SIZE:
265 for row in self.__store:
266 if row[self.COL_ID] == albumid:
267 row[self.COL_ICON] = self.get_pixbuf(cover)
269 def add_playlist(self, name, tracks):
273 return "(%d tracks)"%(ln)
277 track = tracks[0] if len(tracks) else None
278 track_album_id = int(track['data']['album_id']) if track else 0
279 self.__store.append([self.get_default_pixbuf(), name, trackcount(tracks), track_album_id])
281 postoffice.notify('request-album-cover', track_album_id, self.ICON_SIZE)
283 def get_playlist_name(self, path):
284 return self.__store.get(self.__store.get_iter(path), self.COL_NAME)[0]
286 class RadioList(_BaseList):
288 _BaseList.__init__(self)
289 (self.COL_ICON, self.COL_NAME, self.COL_ID, self.COL_IMAGE) = range(4)
290 self.__store = gtk.ListStore(gtk.gdk.Pixbuf, str, int, str)
291 self.set_model(self.__store)
293 icon = gtk.TreeViewColumn('Icon')
294 self.append_column(icon)
295 cell = gtk.CellRendererPixbuf()
296 icon.pack_start(cell, True)
297 icon.add_attribute(cell, 'pixbuf', self.COL_ICON)
299 col = gtk.TreeViewColumn('Name')
300 self.append_column(col)
301 cell = gtk.CellRendererText()
302 col.pack_start(cell, True)
303 col.add_attribute(cell, 'text', self.COL_NAME)
304 self.set_search_column(self.COL_NAME)
305 col.set_sort_column_id(self.COL_NAME)
307 postoffice.connect('images', self, self.on_images)
309 def on_destroy(self, wnd):
310 postoffice.disconnect('images', self)
312 def add_radios(self, radios):
314 self.__store.append([self.get_default_pixbuf(), self.radio_name(radio), radio.ID, radio.image])
315 postoffice.notify('request-images', [radio.image for radio in radios])
318 def get_radio_id(self, path):
319 treeiter = self.__store.get_iter(path)
320 name, _id = self.__store.get(treeiter, self.COL_NAME, self.COL_ID)
323 def on_images(self, images):
324 for url, image in images:
325 for row in self.__store:
326 if row[self.COL_IMAGE] == url:
327 pb = self.get_pixbuf(image)
329 row[self.COL_ICON] = pb
331 def radio_name(self, radio):
333 return radio.idstr.capitalize()
337 return "Radio #%s" % (radio.ID)