def update(self, media): """Update the stack with the given media Update the stack with the art retrieved from the given media. :param Grl.Media media: The media object """ self._active_child = self._stack.get_visible_child_name() art = Art(self._size, media, self._scale) self._handler_id = art.connect('finished', self._art_retrieved) art.lookup()
def _add_item(self, source, param, item, remaining=0, data=None): if data is None: return model, category = data self._items_found = ( self.model.iter_n_children(self._head_iters[0]) + self.model.iter_n_children(self._head_iters[1]) + self.model.iter_n_children(self._head_iters[2]) + self.model.iter_n_children(self._head_iters[3]) ) if (category == 'song' and self._items_found == 0 and remaining == 0): if grilo.search_source: self.emit('no-music-found') # We need to remember the view before the search view emptysearchview = self._window.views[View.EMPTY_SEARCH] if (self._window.curr_view != emptysearchview and self._window.prev_view != emptysearchview): self.previous_view = self._window.prev_view if remaining == 0: self._window.notifications_popup.pop_loading() self._view.show() if not item or model != self.model: return self._offset += 1 title = utils.get_media_title(item) item.set_title(title) artist = utils.get_artist_name(item) group = 3 try: group = {'album': 0, 'artist': 1, 'song': 2}[category] except: pass _iter = None if category == 'album': _iter = self.model.insert_with_values( self._head_iters[group], -1, [0, 2, 3, 5, 9, 11], [str(item.get_id()), title, artist, item, 2, category]) elif category == 'song': # FIXME: source specific hack if source.get_id() != 'grl-tracker-source': fav = 2 else: fav = item.get_favourite() _iter = self.model.insert_with_values( self._head_iters[group], -1, [0, 2, 3, 5, 9, 11], [str(item.get_id()), title, artist, item, fav, category]) else: if not artist.casefold() in self._artists: _iter = self.model.insert_with_values( self._head_iters[group], -1, [0, 2, 5, 9, 11], [str(item.get_id()), artist, item, 2, category]) self._artists[artist.casefold()] = { 'iter': _iter, 'albums': [] } self._artists[artist.casefold()]['albums'].append(item) # FIXME: Figure out why iter can be None here, seems illogical. if _iter is not None: scale = self._view.get_scale_factor() art = Art(Art.Size.SMALL, item, scale) self.model[_iter][13] = art.surface art.connect( 'finished', self._retrieval_finished, self.model, _iter) art.lookup() if self.model.iter_n_children(self._head_iters[group]) == 1: path = self.model.get_path(self._head_iters[group]) path = self._filter_model.convert_child_path_to_path(path) self._view.get_generic_view().expand_row(path, False)
class CoverStack(Gtk.Stack): """Provides a smooth transition between image states Uses a Gtk.Stack to provide an in-situ transition between an image state. Either between the 'loading' state versus the 'loaded' state or in between songs. """ __gtype_name__ = 'CoverStack' __gsignals__ = {'updated': (GObject.SignalFlags.RUN_FIRST, None, ())} _default_icon = DefaultIcon() def __repr__(self): return '<CoverStack>' @log def __init__(self, size=Art.Size.MEDIUM): """Initialize the CoverStack :param Art.Size size: The size of the art used for the cover """ super().__init__() self._art = None self._handler_id = None self._size = None self._timeout = None self._loading_cover = Gtk.Image() self._cover_a = Gtk.Image() self._cover_b = Gtk.Image() self.add_named(self._loading_cover, "loading") self.add_named(self._cover_a, "A") self.add_named(self._cover_b, "B") self.props.size = size self.props.transition_type = Gtk.StackTransitionType.CROSSFADE self.props.visible_child_name = "loading" self.show_all() @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE) def size(self): """Size of the cover :returns: The size used :rtype: Art.Size """ return self._size @size.setter def size(self, value): """Set the cover size :param Art.Size value: The size to use for the cover """ self._size = value icon = self._default_icon.get(DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor) self._loading_cover.props.surface = icon @log def update(self, coresong): """Update the stack with the given CoreSong Update the stack with the art retrieved from the given Coresong. :param CoreSong coresong: The CoreSong object """ if self._handler_id and self._art: # Remove a possible dangling 'finished' callback if update # is called again, but it is still looking for the previous # art. self._art.disconnect(self._handler_id) # Set the loading state only after a delay to make between # song transitions smooth if loading time is negligible. self._timeout = GLib.timeout_add(100, self._set_loading_child) self._active_child = self.props.visible_child_name self._art = Art(self.props.size, coresong, self.props.scale_factor) self._handler_id = self._art.connect('finished', self._art_retrieved) self._art.lookup() @log def _set_loading_child(self): self.props.visible_child_name = "loading" self._active_child = self.props.visible_child_name self._timeout = None return GLib.SOURCE_REMOVE @log def _art_retrieved(self, klass): if self._timeout: GLib.source_remove(self._timeout) self._timeout = None if self._active_child == "B": self._cover_a.props.surface = klass.surface self.props.visible_child_name = "A" else: self._cover_b.props.surface = klass.surface self.props.visible_child_name = "B" self._active_child = self.props.visible_child_name self._art = None self.emit('updated')
class ArtistArtStack(Gtk.Stack): """Provides a smooth transition between image states Uses a Gtk.Stack to provide an in-situ transition between an image state. Either between the "loading" state versus the "loaded" state or in between songs. """ __gtype_name__ = "ArtistArtStack" _default_icon = DefaultIcon() def __repr__(self): return "ArtistArtStack" @log def __init__(self, size=Art.Size.MEDIUM): """Initialize the CoverStack :param Art.Size size: The size of the art used for the cover """ super().__init__() self._art = None self._handler_id = None self._size = None self._timeout = None self._loading_cover = Gtk.Image() self._cover_a = Gtk.Image() self._cover_b = Gtk.Image() self.add_named(self._loading_cover, "loading") self.add_named(self._cover_a, "A") self.add_named(self._cover_b, "B") self._active_child = "loading" self.props.size = size self.props.transition_type = Gtk.StackTransitionType.CROSSFADE self.props.visible_child_name = "loading" self.show_all() @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE) def size(self): """Size of the cover :returns: The size used :rtype: Art.Size """ return self._size @size.setter def size(self, value): """Set the cover size :param Art.Size value: The size to use for the cover """ self._size = value icon = self._default_icon.get(DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor) self._loading_cover.props.surface = icon @GObject.Property(type=CoreArtist, default=None) def coreartist(self): return self._coreartist @coreartist.setter def coreartist(self, coreartist): self._coreartist = coreartist self._coreartist.connect("notify::cached-thumbnail-uri", self._on_thumbnail_changed) if self._coreartist.props.thumbnail is not None: self._on_thumbnail_changed(self._coreartist, None) def _on_thumbnail_changed(self, coreartist, uri): cache = ArtistCache(self.props.size, self.props.scale_factor) cache.connect("result", self._on_cache_result) cache.query(coreartist) def _on_cache_result(self, cache, surface): if self._active_child == "B": self._cover_a.props.surface = surface self.props.visible_child_name = "A" else: self._cover_b.props.surface = surface self.props.visible_child_name = "B" @log def update(self, coresong): """Update the stack with the given CoreSong Update the stack with the art retrieved from the given Coresong. :param CoreSong coresong: The CoreSong object """ if self._handler_id and self._art: # Remove a possible dangling "finished" callback if update # is called again, but it is still looking for the previous # art. self._art.disconnect(self._handler_id) # Set the loading state only after a delay to make between # song transitions smooth if loading time is negligible. self._timeout = GLib.timeout_add(100, self._set_loading_child) self._active_child = self.props.visible_child_name self._art = Art(self.props.size, coresong, self.props.scale_factor) self._handler_id = self._art.connect("finished", self._art_retrieved) self._art.lookup() @log def _set_loading_child(self): self.props.visible_child_name = "loading" self._active_child = self.props.visible_child_name self._timeout = None return GLib.SOURCE_REMOVE @log def _art_retrieved(self, klass): if self._timeout: GLib.source_remove(self._timeout) self._timeout = None if self._active_child == "B": self._cover_a.props.surface = klass.surface self.props.visible_child_name = "A" else: self._cover_b.props.surface = klass.surface self.props.visible_child_name = "B" self._active_child = self.props.visible_child_name self._art = None
class CoverStack(Gtk.Stack): """Provides a smooth transition between image states Uses a Gtk.Stack to provide an in-situ transition between an image state. Either between the 'loading' state versus the 'loaded' state or in between songs. """ __gtype_name__ = 'CoverStack' __gsignals__ = { 'updated': (GObject.SignalFlags.RUN_FIRST, None, ()) } _default_icon = DefaultIcon() def __repr__(self): return '<CoverStack>' @log def __init__(self, size=Art.Size.MEDIUM): """Initialize the CoverStack :param Art.Size size: The size of the art used for the cover """ super().__init__() self._art = None self._handler_id = None self._size = None self._timeout = None self._loading_cover = Gtk.Image() self._cover_a = Gtk.Image() self._cover_b = Gtk.Image() self.add_named(self._loading_cover, "loading") self.add_named(self._cover_a, "A") self.add_named(self._cover_b, "B") self.props.size = size self.props.transition_type = Gtk.StackTransitionType.CROSSFADE self.props.visible_child_name = "loading" self.show_all() @GObject.Property(type=object, flags=GObject.ParamFlags.READWRITE) def size(self): """Size of the cover :returns: The size used :rtype: Art.Size """ return self._size @size.setter def size(self, value): """Set the cover size :param Art.Size value: The size to use for the cover """ self._size = value icon = self._default_icon.get( DefaultIcon.Type.LOADING, self.props.size, self.props.scale_factor) self._loading_cover.props.surface = icon @log def update(self, media): """Update the stack with the given media Update the stack with the art retrieved from the given media. :param Grl.Media media: The media object """ if self._handler_id and self._art: # Remove a possible dangling 'finished' callback if update # is called again, but it is still looking for the previous # art. self._art.disconnect(self._handler_id) # Set the loading state only after a delay to make between # song transitions smooth if loading time is negligible. self._timeout = GLib.timeout_add(100, self._set_loading_child) self._active_child = self.props.visible_child_name self._art = Art(self.props.size, media, self.props.scale_factor) self._handler_id = self._art.connect('finished', self._art_retrieved) self._art.lookup() @log def _set_loading_child(self): self.props.visible_child_name = "loading" self._active_child = self.props.visible_child_name self._timeout = None return GLib.SOURCE_REMOVE @log def _art_retrieved(self, klass): if self._timeout: GLib.source_remove(self._timeout) self._timeout = None if self._active_child == "B": self._cover_a.props.surface = klass.surface self.props.visible_child_name = "A" else: self._cover_b.props.surface = klass.surface self.props.visible_child_name = "B" self._active_child = self.props.visible_child_name self._art = None self.emit('updated')