def _on_label_button_release(self, eventbox, event):
     """
         Show artists information
         @param eventbox as Gtk.EventBox
         @param event as Gdk.Event
     """
     if len(self._artist_ids) == 1:
         from lollypop.pop_information import InformationPopover
         self.__pop_info = InformationPopover(True)
         self.__pop_info.set_relative_to(eventbox)
         self.__pop_info.populate(self._artist_ids[0])
         self.__pop_info.show()
 def __on_button_press_event(self, widget, event):
     """
         Show current track menu
         @param widget as Gtk.Widget
         @param event as Gdk.Event
     """
     if event.button == 1:
         if App().player.current_track.id == Type.RADIOS:
             from lollypop.pop_tunein import TuneinPopover
             popover = TuneinPopover()
             popover.populate()
         elif App().player.current_track.id is not None:
             from lollypop.pop_information import InformationPopover
             popover = InformationPopover()
             popover.populate()
         popover.set_relative_to(self._infobox)
         popover.popup()
     else:
         from lollypop.pop_menu import ToolbarMenu
         menu = ToolbarMenu(App().player.current_track)
         if App().player.current_track.id >= 0:
             from lollypop.pop_menu import TrackMenuPopover
             popover = TrackMenuPopover(App().player.current_track, menu)
             popover.set_relative_to(self._infobox)
         elif App().player.current_track.id == Type.RADIOS:
             popover = Popover.new_from_model(self._infobox, menu)
         popover.popup()
     return True
Example #3
0
 def _on_primary_press_gesture(self, x, y, event):
     """
         Show information popover
         @param x as int
         @param y as int
         @param evnet as Gdk.Event
     """
     if App().window.folded or not self.__artwork.get_visible():
         return
     if App().player.current_track.id is not None:
         from lollypop.pop_information import InformationPopover
         popover = InformationPopover()
         popover.populate()
     popover.set_relative_to(self.__eventbox)
     popover.popup()
 def __on_button_release_event(self, widget, event):
     """
         Handle buttons
         @param widget as Gtk.Widget
         @param event as Gdk.Event
     """
     if App().window.is_adaptive or not self._artwork.get_visible():
         return
     if App().player.current_track.id == Type.RADIOS:
         from lollypop.pop_tunein import TuneinPopover
         popover = TuneinPopover()
         popover.populate()
     elif App().player.current_track.id is not None:
         from lollypop.pop_information import InformationPopover
         popover = InformationPopover()
         popover.populate()
     popover.set_relative_to(self._infobox)
     popover.popup()
     return True
class ArtistViewCommon:
    """
        Widgets and methods share between ArtistView and ArtistViewSmall
    """
    def __init__(self):
        """
            Init view
        """
        builder = Gtk.Builder()
        builder.add_from_resource("/org/gnome/Lollypop/ArtistView.ui")
        builder.connect_signals(self)
        builder.get_object("box-button").set_margin_end(MARGIN)
        self._artwork = builder.get_object("artwork")
        self._title_label = builder.get_object("artist")
        self._title_label.connect("realize", on_realize)
        self._title_label.connect("query-tooltip", on_query_tooltip)
        self._title_label.set_property("has-tooltip", True)
        self._jump_button = builder.get_object("jump-button")
        self._add_button = builder.get_object("add-button")
        self._play_button = builder.get_object("play-button")
        self._buttons = builder.get_object("buttons")
        self._banner = ArtistBannerWidget(self._artist_ids[0])
        self._banner.add_overlay(self._buttons)
        self._banner.show()
        builder.get_object("box-button").set_margin_end(MARGIN)
        artists = []
        for artist_id in self._artist_ids:
            artists.append(App().artists.get_name(artist_id))
        self._title_label.set_markup(
            GLib.markup_escape_text(", ".join(artists)))

#######################
# PROTECTED           #
#######################

    def _update_icon(self, add):
        """
            Set icon for Artist +/-
            @param add as bool
        """
        if add:
            # Translators: artist context
            self._add_button.set_tooltip_text(_("Add to current playlist"))
            self._add_button.get_image().set_from_icon_name(
                "list-add-symbolic", Gtk.IconSize.DND)
        else:
            # Translators: artist context
            self._add_button.set_tooltip_text(
                _("Remove from current playlist"))
            self._add_button.get_image().set_from_icon_name(
                "list-remove-symbolic", Gtk.IconSize.DND)

    def _on_label_realize(self, eventbox):
        pass

    def _on_artwork_box_realize(self, eventbox):
        pass

    def _on_image_button_release(self, eventbox, event):
        pass

    def _on_jump_button_clicked(self, button):
        pass

    def _on_label_button_release(self, eventbox, event):
        """
            Show artists information
            @param eventbox as Gtk.EventBox
            @param event as Gdk.Event
        """
        if len(self._artist_ids) == 1:
            from lollypop.pop_information import InformationPopover
            self.__pop_info = InformationPopover(True)
            self.__pop_info.set_relative_to(eventbox)
            self.__pop_info.populate(self._artist_ids[0])
            self.__pop_info.show()

    def _on_play_clicked(self, widget):
        """
            Play artist albums
        """
        try:
            if App().player.is_party:
                App().lookup_action("party").change_state(
                    GLib.Variant("b", False))
            App().player.play_albums(None, self._genre_ids, self._artist_ids)
            self._update_icon(False)
        except Exception as e:
            Logger.error("ArtistView::_on_play_clicked: %s" % e)

    def _on_add_clicked(self, widget):
        """
            Add artist albums
        """
        try:
            if App().settings.get_value("show-performers"):
                album_ids = App().tracks.get_album_ids(self._artist_ids,
                                                       self._genre_ids)
            else:
                album_ids = App().albums.get_ids(self._artist_ids,
                                                 self._genre_ids)
            icon_name = self._add_button.get_image().get_icon_name()[0]
            add = icon_name == "list-add-symbolic"
            for album_id in album_ids:
                if add and album_id not in App().player.album_ids:
                    App().player.add_album(
                        Album(album_id, self._genre_ids, self._artist_ids))
                elif not add and album_id in App().player.album_ids:
                    App().player.remove_album_by_id(album_id)
            if len(App().player.album_ids) == 0:
                App().player.stop()
            elif App().player.current_track.album.id\
                    not in App().player.album_ids:
                App().player.skip_album()
            self._update_icon(not add)
        except Exception as e:
            Logger.error("ArtistView::_on_add_clicked: %s" % e)

    def _on_similars_button_toggled(self, button):
        """
            Show similar artists
            @param button as Gtk.Button
        """
        if button.get_active():
            from lollypop.pop_similars import SimilarsPopover
            popover = SimilarsPopover()
            popover.set_relative_to(button)
            popover.populate(self._artist_ids)
            popover.connect("closed", lambda x: button.set_active(False))
            popover.popup()
class ArtistBannerWidget(BannerWidget, SignalsHelper):
    """
        Banner for artist
    """

    @signals_map
    def __init__(self, genre_ids, artist_ids, storage_type, view_type):
        """
            Init artist banner
            @parma genre_ids as [int]
            @param artist_ids as [int]
            @param storage_type as StorageType
            @param view_type as ViewType (Unused)
        """
        BannerWidget.__init__(self, view_type | ViewType.OVERLAY)
        self.__genre_ids = genre_ids
        self.__artist_ids = artist_ids
        self.__storage_type = storage_type
        builder = Gtk.Builder()
        builder.add_from_resource("/org/gnome/Lollypop/ArtistBannerWidget.ui")
        builder.connect_signals(self)
        self.__badge_artwork = builder.get_object("badge_artwork")
        self.__labels = builder.get_object("label_event")
        self.__title_label = builder.get_object("artist")
        self.__title_label.connect("realize", set_cursor_type)
        self.__title_label.connect("query-tooltip", on_query_tooltip)
        self.__title_label.set_property("has-tooltip", True)
        self.__add_button = builder.get_object("add_button")
        self.__play_button = builder.get_object("play_button")
        self.__menu_button = builder.get_object("menu_button")
        if len(artist_ids) > 1:
            self.__menu_button.hide()
        builder.get_object("artwork_event").connect(
            "realize", set_cursor_type)
        self.__labels.connect("realize", set_cursor_type)
        self.__widget = builder.get_object("widget")
        artists = []
        for artist_id in self.__artist_ids:
            artists.append(App().artists.get_name(artist_id))
        self.__title_label.set_markup(GLib.markup_escape_text(
            ", ".join(artists)))
        self.__show_artwork = len(artist_ids) == 1
        self.__title_label.get_style_context().add_class("text-x-large")
        self._overlay.add_overlay(self.__widget)
        self._overlay.set_overlay_pass_through(self.__widget, True)
        self.__update_add_button()
        self.__set_internal_size()
        return [
               (App().window.container.widget, "notify::folded",
                "_on_container_folded"),
               (App().art, "artist-artwork-changed",
                "_on_artist_artwork_changed"),
               (App().player, "playback-added", "_on_playback_changed"),
               (App().player, "playback-updated", "_on_playback_changed"),
               (App().player, "playback-setted", "_on_playback_changed"),
               (App().player, "playback-removed", "_on_playback_changed"),
               (App().settings, "changed::artist-artwork",
                "_on_artist_artwork_setting_changed")

        ]

    def update_for_width(self, width):
        """
            Update banner internals for width, call this before showing banner
            @param width as int
        """
        BannerWidget.update_for_width(self, width)
        self.__set_artwork()

#######################
# PROTECTED           #
#######################
    def _handle_width_allocate(self, allocation):
        """
            Update artwork
            @param allocation as Gtk.Allocation
        """
        if BannerWidget._handle_width_allocate(self, allocation):
            self.__set_artwork()

    def _on_container_folded(self, leaflet, folded):
        """
            Handle libhandy folded status
            @param leaflet as Handy.Leaflet
            @param folded as Gparam
        """
        self.__set_internal_size()

    def _on_artist_artwork_setting_changed(self, settings, variant):
        """
            Update banner
            @param settings as Gio.Settings
            @param value as GLib.Variant
        """
        self.__set_artwork()

    def _on_label_button_release(self, eventbox, event):
        """
            Show artists information
            @param eventbox as Gtk.EventBox
            @param event as Gdk.Event
        """
        if len(self.__artist_ids) == 1:
            from lollypop.pop_information import InformationPopover
            self.__pop_info = InformationPopover(True)
            self.__pop_info.set_relative_to(eventbox)
            self.__pop_info.populate(self.__artist_ids[0])
            self.__pop_info.show()

    def _on_play_clicked(self, *ignore):
        """
            Play artist albums
        """
        play_artists(self.__artist_ids, self.__genre_ids)

    def _on_add_clicked(self, *ignore):
        """
            Add artist albums
        """
        icon_name = self.__add_button.get_image().get_icon_name()[0]
        add = icon_name == "list-add-symbolic"
        add_artist_to_playback(self.__artist_ids, self.__genre_ids, add)

    def _on_menu_button_clicked(self, button):
        """
            Show album menu
            @param button as Gtk.Button
        """
        from lollypop.widgets_menu import MenuBuilder
        from lollypop.menu_artist import ArtistMenu
        from lollypop.menu_similars import SimilarsMenu
        from lollypop.menu_artwork import ArtistArtworkMenu
        menu = ArtistMenu(self.__artist_ids[0],
                          self.__storage_type,
                          self.view_type,
                          App().window.folded)
        menu_widget = MenuBuilder(menu, False)
        menu_widget.show()
        menu_ext = SimilarsMenu(self.__artist_ids[0])
        menu_ext.show()
        menu_widget.add_widget(menu_ext)
        if App().window.folded:
            menu_ext2 = ArtistArtworkMenu(self.__artist_ids[0],
                                          self.view_type,
                                          True)
            menu_ext2.connect("hidden", self.__close_artwork_menu)
            menu_ext2.show()
            menu_widget.add_widget(menu_ext2)
        popup_widget(menu_widget, button, None, None, button)

    def _on_badge_button_release(self, eventbox, event):
        """
            Show artist artwork manager
            @param eventbox as Gtk.EventBox
            @param event as Gdk.Event
        """
        from lollypop.widgets_menu import MenuBuilder
        from lollypop.menu_artwork import ArtistArtworkMenu
        menu = Gio.Menu()
        if App().window.folded:
            from lollypop.menu_header import ArtistMenuHeader
            menu.append_item(ArtistMenuHeader(self.__artist_ids[0]))
        menu_widget = MenuBuilder(menu, False)
        menu_widget.show()
        menu_ext = ArtistArtworkMenu(self.__artist_ids[0],
                                     self.view_type,
                                     False)
        menu_ext.connect("hidden", self.__close_artwork_menu)
        menu_ext.show()
        menu_widget.add_widget(menu_ext)
        self.__artwork_popup = popup_widget(menu_widget,
                                            eventbox,
                                            None, None, None)

    def _on_artist_artwork_changed(self, art, prefix):
        """
            Update artwork if needed
            @param art as Art
            @param prefix as str
        """
        if len(self.__artist_ids) == 1:
            artist = App().artists.get_name(self.__artist_ids[0])
            if prefix == artist:
                self.__set_artwork()
                self.__set_internal_size()

    def _on_playback_changed(self, *ignore):
        """
            Update add button
        """
        self.__update_add_button()

#######################
# PRIVATE             #
#######################
    def __close_artwork_menu(self, action, variant):
        if App().window.folded:
            App().window.container.go_back()
        else:
            self.__artwork_popup.destroy()

    def __set_artwork(self):
        """
            Set artwork
        """
        if App().settings.get_value("artist-artwork") and App().animations:
            artist = App().artists.get_name(choice(self.__artist_ids))
            App().art_helper.set_artist_artwork(
                                        artist,
                                        # +100 to prevent resize lag
                                        self.width + 100,
                                        self.height,
                                        self.get_scale_factor(),
                                        ArtBehaviour.BLUR_HARD |
                                        ArtBehaviour.DARKER,
                                        self._on_artwork)
        else:
            self._artwork.get_style_context().add_class("default-banner")
        if self.width < ArtSize.BANNER * 3:
            if self.__widget.get_child_at(1, 0) == self.__labels:
                self.__widget.remove(self.__labels)
                self.__widget.attach(self.__labels, 2, 2, 3, 1)
        elif self.__widget.get_child_at(2, 2) == self.__labels:
            self.__widget.remove(self.__labels)
            self.__widget.attach(self.__labels, 1, 0, 1, 3)

    def __set_badge_artwork(self, art_size):
        """
            Set artist artwork on badge
            @param art_size as int
        """
        if self.__show_artwork and\
                App().settings.get_value("artist-artwork"):
            artist = App().artists.get_name(self.__artist_ids[0])
            App().art_helper.set_artist_artwork(
                                        artist,
                                        art_size,
                                        art_size,
                                        self.get_scale_factor(),
                                        ArtBehaviour.ROUNDED |
                                        ArtBehaviour.CROP_SQUARE |
                                        ArtBehaviour.CACHE,
                                        self.__on_badge_artist_artwork,
                                        art_size)
        else:
            self.__badge_artwork.hide()

    def __set_internal_size(self):
        """
            Set content size based on current width
        """
        # Text size
        title_context = self.__title_label.get_style_context()
        for c in title_context.list_classes():
            title_context.remove_class(c)
        if App().window.folded:
            art_size = ArtSize.MEDIUM
            cls = "text-large"
        else:
            art_size = ArtSize.BANNER
            cls = "text-x-large"
        self.__title_label.get_style_context().add_class(cls)
        self.__set_badge_artwork(art_size)

    def __update_add_button(self):
        """
            Set image as +/-
        """
        album_ids = App().albums.get_ids(self.__genre_ids, self.__artist_ids,
                                         self.__storage_type, False)
        add = set(App().player.album_ids) & set(album_ids) != set(album_ids)
        if add:
            # Translators: artist context
            self.__add_button.set_tooltip_text(_("Add to current playlist"))
            self.__add_button.get_image().set_from_icon_name(
                "list-add-symbolic",
                Gtk.IconSize.BUTTON)
        else:
            # Translators: artist context
            self.__add_button.set_tooltip_text(
                _("Remove from current playlist"))
            self.__add_button.get_image().set_from_icon_name(
                "list-remove-symbolic",
                Gtk.IconSize.BUTTON)

    def __on_badge_artist_artwork(self, surface, art_size):
        """
            Set artist artwork on badge
            @param surface as cairo.Surface
            @param art_size as int
        """
        if surface is None:
            self.__badge_artwork.get_style_context().add_class("circle-icon")
            self.__badge_artwork.set_size_request(art_size, art_size)
            self.__badge_artwork.set_from_icon_name(
                                              "avatar-default-symbolic",
                                              Gtk.IconSize.DIALOG)
        else:
            self.__badge_artwork.get_style_context().remove_class(
                "circle-icon")
            self.__badge_artwork.set_from_surface(surface)
            del surface