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