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 Gtk, Pango, GLib 14 15from gettext import gettext as _ 16 17from lollypop.define import App, ArtSize, ViewType, Size 18from lollypop.define import MARGIN 19from lollypop.widgets_banner import BannerWidget 20from lollypop.utils import emit_signal, popup_widget, get_human_duration 21from lollypop.helper_signals import SignalsHelper, signals_map 22 23 24class CurrentAlbumsBannerWidget(BannerWidget, SignalsHelper): 25 """ 26 Banner for current albums 27 """ 28 29 @signals_map 30 def __init__(self, view): 31 """ 32 Init banner 33 @param view as AlbumsListView 34 """ 35 BannerWidget.__init__(self, view.view_type | ViewType.OVERLAY) 36 self.__duration_task = False 37 self.__view = view 38 self.__clear_button = Gtk.Button.new_from_icon_name( 39 "edit-clear-all-symbolic", 40 Gtk.IconSize.BUTTON) 41 self.__clear_button.set_relief(Gtk.ReliefStyle.NONE) 42 self.__clear_button.set_tooltip_text(_("Clear albums")) 43 self.__clear_button.set_sensitive(App().player.albums) 44 self.__clear_button.connect("clicked", self.__on_clear_button_clicked) 45 self.__clear_button.get_style_context().add_class("banner-button") 46 self.__clear_button.show() 47 self.__menu_button = Gtk.Button.new_from_icon_name( 48 "view-more-symbolic", 49 Gtk.IconSize.BUTTON) 50 self.__menu_button.set_relief(Gtk.ReliefStyle.NONE) 51 self.__menu_button.set_sensitive(App().player.albums) 52 self.__menu_button.connect("clicked", self.__on_menu_button_clicked) 53 self.__menu_button.get_style_context().add_class("banner-button") 54 self.__menu_button.show() 55 self.__jump_button = Gtk.Button.new_from_icon_name( 56 "go-jump-symbolic", 57 Gtk.IconSize.BUTTON) 58 self.__jump_button.set_relief(Gtk.ReliefStyle.NONE) 59 self.__jump_button.connect("clicked", self.__on_jump_button_clicked) 60 self.__jump_button.set_tooltip_text(_("Go to current track")) 61 self.__jump_button.set_sensitive(App().player.albums) 62 self.__jump_button.get_style_context().add_class("banner-button") 63 self.__jump_button.show() 64 self.__title_label = Gtk.Label.new( 65 "<b>" + _("Playing albums") + "</b>") 66 self.__title_label.show() 67 self.__title_label.set_use_markup(True) 68 self.__title_label.set_hexpand(True) 69 self.__title_label.get_style_context().add_class("dim-label") 70 self.__title_label.set_property("halign", Gtk.Align.START) 71 self.__title_label.set_ellipsize(Pango.EllipsizeMode.END) 72 self.__duration_label = Gtk.Label.new() 73 self.__duration_label.show() 74 self.__duration_label.set_property("halign", Gtk.Align.END) 75 grid = Gtk.Grid() 76 grid.show() 77 grid.set_column_spacing(MARGIN) 78 grid.set_property("valign", Gtk.Align.CENTER) 79 grid.set_margin_start(MARGIN) 80 grid.set_margin_end(MARGIN) 81 grid.add(self.__title_label) 82 grid.add(self.__duration_label) 83 buttons = Gtk.Grid() 84 buttons.show() 85 buttons.get_style_context().add_class("linked") 86 buttons.set_property("valign", Gtk.Align.CENTER) 87 buttons.add(self.__jump_button) 88 buttons.add(self.__clear_button) 89 buttons.add(self.__menu_button) 90 grid.add(buttons) 91 self._overlay.add_overlay(grid) 92 self._overlay.set_overlay_pass_through(grid, True) 93 self.connect("destroy", self.__on_destroy) 94 return [ 95 (view, "initialized", "_on_view_updated"), 96 (App().player, "playback-added", "_on_playback_changed"), 97 (App().player, "playback-updated", "_on_playback_changed"), 98 (App().player, "playback-setted", "_on_playback_changed"), 99 (App().player, "playback-removed", "_on_playback_changed"), 100 ] 101 102 def update_for_width(self, width): 103 """ 104 Update banner internals for width, call this before showing banner 105 @param width as int 106 """ 107 BannerWidget.update_for_width(self, width) 108 self.__set_internal_size() 109 110 @property 111 def spinner(self): 112 """ 113 Get banner spinner 114 @return Gtk.Spinner 115 """ 116 return self.__spinner 117 118 @property 119 def entry(self): 120 """ 121 Get banner entry 122 @return Gtk.Entry 123 """ 124 return self.__entry 125 126 @property 127 def clear_button(self): 128 """ 129 Get clear button 130 @return Gtk.Button 131 """ 132 return self.__clear_button 133 134 @property 135 def menu_button(self): 136 """ 137 Get menu button 138 @return Gtk.Button 139 """ 140 return self.__menu_button 141 142 @property 143 def jump_button(self): 144 """ 145 Get jump button 146 @return Gtk.Button 147 """ 148 return self.__jump_button 149 150 @property 151 def height(self): 152 """ 153 Get wanted height 154 @return int 155 """ 156 return ArtSize.SMALL 157 158####################### 159# PROTECTED # 160####################### 161 def _handle_width_allocate(self, allocation): 162 """ 163 Update artwork 164 @param allocation as Gtk.Allocation 165 """ 166 if BannerWidget._handle_width_allocate(self, allocation): 167 self.__set_internal_size() 168 169 def _on_view_updated(self, view): 170 """ 171 @param view as AlbumsListView 172 """ 173 if self.__view.children: 174 self.__duration_task = True 175 App().task_helper.run(self.__calculate_duration) 176 else: 177 self.__duration_task = False 178 self.__duration_label.set_text(get_human_duration(0)) 179 180 def _on_playback_changed(self, player, *ignore): 181 """ 182 Update clear button state 183 @param player as Player 184 """ 185 sensitive = player.albums != [] 186 GLib.idle_add(self.__clear_button.set_sensitive, sensitive) 187 GLib.idle_add(self.__clear_button.set_sensitive, sensitive) 188 GLib.idle_add(self.__jump_button.set_sensitive, sensitive) 189 GLib.idle_add(self.__menu_button.set_sensitive, sensitive) 190 self.__duration_task = True 191 App().task_helper.run(self.__calculate_duration) 192 193####################### 194# PRIVATE # 195####################### 196 def __calculate_duration(self): 197 """ 198 Calculate playback duration 199 """ 200 GLib.idle_add(self.__duration_label.set_text, "") 201 duration = 0 202 for child in self.__view.children: 203 if not self.__duration_task: 204 return 205 duration += child.album.duration 206 self.__duration_task = False 207 GLib.idle_add(self.__duration_label.set_text, 208 get_human_duration(duration)) 209 210 def __set_internal_size(self): 211 """ 212 Update font size 213 """ 214 duration_context = self.__duration_label.get_style_context() 215 title_context = self.__title_label.get_style_context() 216 for c in title_context.list_classes(): 217 title_context.remove_class(c) 218 for c in duration_context.list_classes(): 219 duration_context.remove_class(c) 220 if self.width <= Size.MEDIUM: 221 title_context.add_class("text-large") 222 else: 223 duration_context.add_class("text-large") 224 title_context.add_class("text-x-large") 225 226 def __on_jump_button_clicked(self, button): 227 """ 228 Scroll to album 229 @param button as Gtk.Button 230 """ 231 self.__view.jump_to_current() 232 233 def __on_menu_button_clicked(self, button): 234 """ 235 Save to playlist 236 @param button as Gtk.Button 237 """ 238 from lollypop.widgets_menu import MenuBuilder 239 from lollypop.menu_current_albums import CurrentAlbumsMenu 240 menu = CurrentAlbumsMenu(App().window.folded) 241 menu_widget = MenuBuilder(menu) 242 menu_widget.show() 243 popup_widget(menu_widget, button, None, None, button) 244 245 def __on_clear_button_clicked(self, button): 246 """ 247 Clear albums 248 @param button as Gtk.Button 249 """ 250 self.__view.clear() 251 self.__view.populate() 252 emit_signal(App().player, "status-changed") 253 254 def __on_destroy(self, widget): 255 """ 256 Remove ref cycle 257 @param widget as Gtk.Widget 258 """ 259 self.__view = None 260