1# Copyright (c) 2014-2021 Cedric Bellegarde <cedric.bellegarde@adishatz.org>
2# This program is free software: you can redistribute it and/or modify
3# it under the terms of the GNU General Public License as published by
4# the Free Software Foundation, either version 3 of the License, or
5# (at your option) any later version.
6# This program is distributed in the hope that it will be useful,
7# but WITHOUT ANY WARRANTY; without even the implied warranty of
8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9# GNU General Public License for more details.
10# You should have received a copy of the GNU General Public License
11# along with this program. If not, see <http://www.gnu.org/licenses/>.
12
13from gi.repository import GLib, Gtk, Pango, GObject
14
15from lollypop.define import App, ArtSize, ViewType, ArtBehaviour
16from lollypop.define import MARGIN, MARGIN_MEDIUM
17from lollypop.utils import on_query_tooltip, emit_signal
18
19
20class AlbumSimpleWidget(Gtk.FlowBoxChild):
21    """
22        Album widget showing cover, artist and title
23    """
24    __gsignals__ = {
25        "populated": (GObject.SignalFlags.RUN_FIRST, None, ()),
26    }
27
28    def __init__(self, album, genre_ids, artist_ids, view_type, font_height):
29        """
30            Init simple album widget
31            @param album as Album
32            @param genre_ids as [int]
33            @param artist_ids as [int]
34            @param view_type as ViewType
35            @parma font_height as int
36        """
37        # We do not use Gtk.Builder for speed reasons
38        Gtk.FlowBoxChild.__init__(self)
39        self.__album = album
40        self.__genre_ids = genre_ids
41        self.__artist_ids = artist_ids
42        self.__artwork = None
43        self.__view_type = view_type
44        self.__font_height = font_height
45        self.set_property("halign", Gtk.Align.CENTER)
46        if view_type & ViewType.ALBUM:
47            self.set_property("margin", MARGIN_MEDIUM)
48        else:
49            self.set_property("margin", MARGIN)
50        self.update_art_size()
51
52    def do_get_preferred_width(self):
53        """
54            Return preferred width
55            @return (int, int)
56        """
57        if self.__artwork is None:
58            return (0, 0)
59        width = Gtk.FlowBoxChild.do_get_preferred_width(self)[0]
60        return (width, width)
61
62    def populate(self):
63        """
64            Populate widget content
65        """
66        if self.__artwork is None:
67            grid = Gtk.Grid()
68            grid.set_orientation(Gtk.Orientation.VERTICAL)
69            grid.set_row_spacing(MARGIN_MEDIUM)
70            self.__label = Gtk.Label.new()
71            self.__label.set_justify(Gtk.Justification.CENTER)
72            self.__label.set_ellipsize(Pango.EllipsizeMode.END)
73            self.__label.set_property("halign", Gtk.Align.CENTER)
74            self.__label.set_property("has-tooltip", True)
75            self.__label.connect("query-tooltip", on_query_tooltip)
76            style_context = self.__label.get_style_context()
77            if self.__view_type & ViewType.SMALL:
78                style_context.add_class("text-small")
79            album_name = GLib.markup_escape_text(self.__album.name)
80            if self.__view_type & ViewType.ALBUM:
81                self.__label.set_markup(album_name)
82            elif self.__view_type & ViewType.ARTIST:
83                if self.__album.year and\
84                        App().settings.get_value("show-year-below-name"):
85                    self.__label.set_markup(
86                        "<b>%s</b>\n<span alpha='25000'>%s</span>" % (
87                            album_name, self.__album.year))
88                else:
89                    self.__label.set_markup("<b>%s</b>" % album_name)
90            else:
91                artist_name = GLib.markup_escape_text(", ".join(
92                                                      self.__album.artists))
93                self.__label.set_markup(
94                    "<b>%s</b>\n<span alpha='50000'>%s</span>" % (album_name,
95                                                                  artist_name))
96            self.__artwork = Gtk.Image.new()
97            grid.add(self.__artwork)
98            grid.add(self.__label)
99            self.set_artwork()
100            self.set_selection()
101            self.connect("destroy", self.__on_destroy)
102            self.add(grid)
103        else:
104            self.set_artwork()
105
106    def update_art_size(self):
107        """
108            Update art size based on current window state
109        """
110        if self.__view_type & ViewType.SMALL:
111            self.__art_size = ArtSize.MEDIUM
112        elif App().window.folded:
113            self.__art_size = ArtSize.BANNER
114        else:
115            self.__art_size = ArtSize.BIG
116        self.set_size_request(self.__art_size,
117                              self.__art_size + self.__font_height * 2)
118
119    def reset_artwork(self):
120        """
121            Reset widget artwork
122        """
123        self.update_art_size()
124        if self.__artwork is not None:
125            self.__artwork.set_from_surface(None)
126
127    def set_artwork(self):
128        """
129            Set artwork
130        """
131        if self.__artwork is None:
132            return
133        if self.__art_size < ArtSize.BIG:
134            frame = "small-cover-frame"
135        else:
136            frame = "cover-frame"
137        App().art_helper.set_frame(self.__artwork,
138                                   frame,
139                                   self.__art_size,
140                                   self.__art_size)
141        App().art_helper.set_album_artwork(self.__album,
142                                           self.__art_size,
143                                           self.__art_size,
144                                           self.__artwork.get_scale_factor(),
145                                           ArtBehaviour.CACHE |
146                                           ArtBehaviour.CROP_SQUARE,
147                                           self.__on_album_artwork)
148
149    def set_selection(self):
150        """
151            Hilight widget if currently playing
152        """
153        if self.__artwork is None:
154            return
155        selected = self.__album.id == App().player.current_track.album.id
156        if selected:
157            self.__artwork.set_state_flags(Gtk.StateFlags.SELECTED, False)
158        else:
159            self.__artwork.unset_state_flags(Gtk.StateFlags.SELECTED)
160
161    @property
162    def data(self):
163        """
164            @return Album
165        """
166        return self.__album
167
168    @property
169    def name(self):
170        """
171            Get name
172            @return str
173        """
174        if self.__view_type & (ViewType.ALBUM | ViewType.ARTIST):
175            return self.__album.name
176        else:
177            return "%s %s" % (self.__album.name, self.__album.artists)
178
179    @property
180    def artwork(self):
181        """
182            Get album artwork
183            @return Gtk.Image
184        """
185        return self.__artwork
186
187    @property
188    def is_populated(self):
189        """
190            True if album populated
191        """
192        return True
193
194#######################
195# PRIVATE             #
196#######################
197    def __on_album_artwork(self, surface):
198        """
199            Set album artwork
200            @param surface as str
201        """
202        if self.__artwork is None:
203            return
204        if surface is None:
205            if self.__art_size == ArtSize.BIG:
206                icon_size = Gtk.IconSize.DIALOG
207            else:
208                icon_size = Gtk.IconSize.DIALOG.DND
209            self.__artwork.set_from_icon_name("folder-music-symbolic",
210                                              icon_size)
211        else:
212            self.__artwork.set_from_surface(surface)
213        self.show_all()
214        emit_signal(self, "populated")
215
216    def __on_destroy(self, widget):
217        """
218            Destroyed widget
219            @param widget as Gtk.Widget
220        """
221        self.__artwork = None
222