def set_row(self, row, track_id, pos, show_cover=False): """ Set row content @param row as Row @param track id as int @param pos as position @param show cover as bool """ track = Track(track_id) row.show_indicator(Lp().player.current_track.id == track_id, utils.is_loved(track_id)) row.set_number(pos) self._update_pos_label(row, track_id) row.set_title_label(track.formated_name()) row.set_duration_label(seconds_to_string(track.duration)) row.set_id(track_id) if show_cover: surface = Lp().art.get_album_artwork( track.album, ArtSize.MEDIUM*row.get_scale_factor()) row.set_cover(surface, track.album.name) del surface row.show_header(True)
class Row(Gtk.ListBoxRow): """ A row """ def __init__(self, rowid, num): """ Init row widgets @param rowid as int @param num as int @param show loved as bool """ # We do not use Gtk.Builder for speed reasons Gtk.ListBoxRow.__init__(self) self._track = Track(rowid) self._number = num self._indicator = IndicatorWidget(self._track.id) self.set_indicator(Lp().player.current_track.id == self._track.id, utils.is_loved(self._track.id)) self._row_widget = Gtk.EventBox() self._row_widget.connect('button-press-event', self._on_button_press) self._row_widget.connect('enter-notify-event', self._on_enter_notify) self._grid = Gtk.Grid() self._grid.set_column_spacing(5) self._row_widget.add(self._grid) self._title_label = Gtk.Label.new(self._track.formated_name()) self._title_label.set_use_markup(True) self._title_label.set_property('has-tooltip', True) self._title_label.connect('query-tooltip', self._on_title_query_tooltip) self._title_label.set_property('hexpand', True) self._title_label.set_property('halign', Gtk.Align.START) self._title_label.set_ellipsize(Pango.EllipsizeMode.END) self._duration_label = Gtk.Label.new( seconds_to_string(self._track.duration)) self._duration_label.get_style_context().add_class('dim-label') self._num_label = Gtk.Label() self._num_label.set_ellipsize(Pango.EllipsizeMode.END) self._num_label.set_property('valign', Gtk.Align.CENTER) self._num_label.set_width_chars(4) self._num_label.get_style_context().add_class('dim-label') self.update_num_label() self._menu_button = Gtk.Button.new() # Here a hack to make old Gtk version support min-height css attribute # min-height = 24px, borders = 2px, we set directly on stack # min-width = 24px, borders = 2px, padding = 8px self._menu_button.set_size_request(34, 26) self._menu_button.set_relief(Gtk.ReliefStyle.NONE) self._menu_button.get_style_context().add_class('menu-button') self._menu_button.get_style_context().add_class('track-menu-button') self._grid.add(self._num_label) self._grid.add(self._title_label) self._grid.add(self._duration_label) # TODO Remove this later if Gtk.get_minor_version() > 16: self._grid.add(self._menu_button) else: self.connect('map', self._on_map) self.add(self._row_widget) self.get_style_context().add_class('trackrow') def set_indicator(self, playing, loved): """ Show indicator @param widget name as str @param playing as bool @param loved as bool """ self._indicator.clear() if playing: self.get_style_context().remove_class('trackrow') self.get_style_context().add_class('trackrowplaying') if loved: self._indicator.play_loved() else: self._indicator.play() else: self.get_style_context().remove_class('trackrowplaying') self.get_style_context().add_class('trackrow') if loved: self._indicator.loved() else: self._indicator.empty() def set_number(self, num): """ Set number @param number as int """ self._number = num def update_num_label(self): """ Update position label for row """ if Lp().player.is_in_queue(self._track.id): self._num_label.get_style_context().add_class('queued') pos = Lp().player.get_track_position(self._track.id) self._num_label.set_text(str(pos)) elif self._number > 0: self._num_label.get_style_context().remove_class('queued') self._num_label.set_text(str(self._number)) else: self._num_label.get_style_context().remove_class('queued') self._num_label.set_text('') def get_id(self): """ Get object id @return Current id as int """ return self._track.id ####################### # PRIVATE # ####################### def _on_map(self, widget): """ Fix for Gtk < 3.18, if we are in a popover, do not show menu button """ widget = self.get_parent() while widget is not None: if isinstance(widget, Gtk.Popover): break widget = widget.get_parent() if widget is None: self._grid.add(self._menu_button) def _on_enter_notify(self, widget, event): """ Set image on buttons now, speed reason @param widget as Gtk.Widget @param event as Gdk.Event """ if self._menu_button.get_image() is None: image = Gtk.Image.new_from_icon_name('open-menu-symbolic', Gtk.IconSize.MENU) image.set_opacity(0.2) self._menu_button.set_image(image) self._menu_button.connect('clicked', self._on_button_clicked) self._indicator.update_button() def _on_button_press(self, widget, event): """ Popup menu for track relative to track row @param widget as Gtk.Widget @param event as Gdk.Event """ if event.button == 3 and Gtk.get_minor_version() > 16: window = widget.get_window() if window == event.window: self._popup_menu(widget, event.x, event.y) # Happens when pressing button over menu btn else: self._popup_menu(self._menu_button) return True elif event.button == 2: if self._track.id in Lp().player.get_queue(): Lp().player.del_from_queue(self._track.id) else: Lp().player.append_to_queue(self._track.id) def _on_button_clicked(self, widget): """ Popup menu for track relative to button @param widget as Gtk.Button """ self._popup_menu(widget) def _popup_menu(self, widget, xcoordinate=None, ycoordinate=None): """ Popup menu for track @param widget as Gtk.Button @param xcoordinate as int (or None) @param ycoordinate as int (or None) """ popover = TrackMenuPopover(self._track.id, TrackMenu(self._track.id)) popover.set_relative_to(widget) if xcoordinate is not None and ycoordinate is not None: rect = widget.get_allocation() rect.x = xcoordinate rect.y = ycoordinate rect.width = rect.height = 1 popover.set_pointing_to(rect) popover.connect('closed', self._on_closed) self.get_style_context().add_class('track-menu-selected') popover.show() def _on_closed(self, widget): """ Remove selected style @param widget as Gtk.Popover """ self.get_style_context().remove_class('track-menu-selected') def _on_title_query_tooltip(self, widget, x, y, keyboard, tooltip): """ Show tooltip if needed @param widget as Gtk.Widget @param x as int @param y as int @param keyboard as bool @param tooltip as Gtk.Tooltip """ layout = self._title_label.get_layout() if layout.is_ellipsized(): self._title_label.set_tooltip_markup(self._track.formated_name()) elif len(self._track.artists) > 1: self._title_label.set_tooltip_text( ", ".join(self._track.artists[1:])) else: self._title_label.set_tooltip_text('')
class Row(Gtk.ListBoxRow): """ A row """ def __init__(self, rowid, num): """ Init row widgets @param rowid as int @param num as int @param show loved as bool """ # We do not use Gtk.Builder for speed reasons Gtk.ListBoxRow.__init__(self) self.set_sensitive(False) self._track = Track(rowid) self._number = num self._indicator = IndicatorWidget(self._track.id) self.set_indicator(Lp().player.current_track.id == self._track.id, utils.is_loved(self._track.id)) self.set_sensitive(True) self._row_widget = Gtk.EventBox() self._row_widget.connect('button-press-event', self._on_button_press) self._row_widget.connect('enter-notify-event', self._on_enter_notify) self._grid = Gtk.Grid() self._grid.set_column_spacing(5) self._row_widget.add(self._grid) self._title_label = Gtk.Label.new(self._track.formated_name()) self._title_label.set_use_markup(True) self._title_label.set_property('has-tooltip', True) self._title_label.connect('query-tooltip', self._on_title_query_tooltip) self._title_label.set_property('hexpand', True) self._title_label.set_property('halign', Gtk.Align.START) self._title_label.set_ellipsize(Pango.EllipsizeMode.END) self._duration_label = Gtk.Label.new( seconds_to_string(self._track.duration)) self._duration_label.get_style_context().add_class('dim-label') self._num_label = Gtk.Label() self._num_label.set_ellipsize(Pango.EllipsizeMode.END) self._num_label.set_property('valign', Gtk.Align.CENTER) self._num_label.set_width_chars(4) self._num_label.get_style_context().add_class('dim-label') self.update_num_label() self._menu_image = Gtk.Image.new() self._menu_image.set_opacity(0.2) self._menu_button = Gtk.Button.new() self._menu_button.set_relief(Gtk.ReliefStyle.NONE) self._menu_button.get_style_context().add_class('menu-button') self._menu_button.get_style_context().add_class('track-menu-button') self._menu_button.set_image(self._menu_image) self._menu_button.connect('clicked', self._on_button_clicked) self._grid.add(self._num_label) self._grid.add(self._title_label) self._grid.add(self._duration_label) # TODO Remove this later if Gtk.get_minor_version() > 16: self._grid.add(self._menu_button) else: self.connect('map', self._on_map) self.add(self._row_widget) self.get_style_context().add_class('trackrow') def set_indicator(self, playing, loved): """ Show indicator @param widget name as str @param playing as bool @param loved as bool """ self._indicator.clear() if playing: self.get_style_context().remove_class('trackrow') self.get_style_context().add_class('trackrowplaying') if loved: self._indicator.play_loved() else: self._indicator.play() else: self.get_style_context().remove_class('trackrowplaying') self.get_style_context().add_class('trackrow') if loved: self._indicator.loved() else: self._indicator.empty() def set_number(self, num): """ Set number @param number as int """ self._number = num def update_num_label(self): """ Update position label for row """ if Lp().player.is_in_queue(self._track.id): self._num_label.get_style_context().add_class('queued') pos = Lp().player.get_track_position(self._track.id) self._num_label.set_text(str(pos)) elif self._number > 0: self._num_label.get_style_context().remove_class('queued') self._num_label.set_text(str(self._number)) else: self._num_label.get_style_context().remove_class('queued') self._num_label.set_text('') def get_id(self): """ Get object id @return Current id as int """ return self._track.id ####################### # PRIVATE # ####################### def _on_map(self, widget): """ Fix for Gtk < 3.18, if we are in a popover, do not show menu button """ widget = self.get_parent() while widget is not None: if isinstance(widget, Gtk.Popover): break widget = widget.get_parent() if widget is None: self._grid.add(self._menu_button) def _on_enter_notify(self, widget, event): """ Set image on buttons now, speed reason @param widget as Gtk.Widget @param event as Gdk.Event """ if self._menu_image.get_pixbuf() is None: self._menu_image.set_from_icon_name('open-menu-symbolic', Gtk.IconSize.MENU) self._indicator.update_button() def _on_button_press(self, widget, event): """ Popup menu for track relative to track row @param widget as Gtk.Widget @param event as Gdk.Event """ if event.button == 3: window = widget.get_window() if window == event.window: self._popup_menu(widget, event.x, event.y) # Happens when pressing button over menu btn else: self._popup_menu(self._menu_button) return True elif event.button == 2: if self._track.id in Lp().player.get_queue(): Lp().player.del_from_queue(self._track.id) else: Lp().player.append_to_queue(self._track.id) def _on_button_clicked(self, widget): """ Popup menu for track relative to button @param widget as Gtk.Button """ self._popup_menu(widget) def _popup_menu(self, widget, xcoordinate=None, ycoordinate=None): """ Popup menu for track @param widget as Gtk.Button @param xcoordinate as int (or None) @param ycoordinate as int (or None) """ popover = TrackMenuPopover(self._track.id, TrackMenu(self._track.id)) popover.set_relative_to(widget) if xcoordinate is not None and ycoordinate is not None: rect = widget.get_allocation() rect.x = xcoordinate rect.y = ycoordinate rect.width = rect.height = 1 popover.set_pointing_to(rect) popover.connect('closed', self._on_closed) self.get_style_context().add_class('track-menu-selected') popover.show() def _on_closed(self, widget): """ Remove selected style @param widget as Gtk.Popover """ self.get_style_context().remove_class('track-menu-selected') def _on_title_query_tooltip(self, widget, x, y, keyboard, tooltip): """ Show tooltip if needed @param widget as Gtk.Widget @param x as int @param y as int @param keyboard as bool @param tooltip as Gtk.Tooltip """ layout = self._title_label.get_layout() if layout.is_ellipsized(): label = self._title_label.get_label() self._title_label.set_tooltip_markup(label) else: self._title_label.set_tooltip_text('')