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, GLib, GObject, Handy 14 15from lollypop.define import App, Type 16from lollypop.utils import emit_signal 17from lollypop.view import View 18from lollypop.container_stack import StackContainer 19from lollypop.container_notification import NotificationContainer 20from lollypop.container_scanner import ScannerContainer 21from lollypop.container_playlists import PlaylistsContainer 22from lollypop.container_lists import ListsContainer 23from lollypop.container_views import ViewsContainer 24from lollypop.container_filter import FilterContainer 25from lollypop.progressbar import ProgressBar 26 27 28class Grid(Gtk.Grid): 29 def do_get_preferred_width(self): 30 return 200, 700 31 32 33class Container(Gtk.Overlay, NotificationContainer, 34 ScannerContainer, PlaylistsContainer, 35 ListsContainer, ViewsContainer, FilterContainer): 36 """ 37 Main view management 38 """ 39 40 __gsignals__ = { 41 "can-go-back-changed": (GObject.SignalFlags.RUN_FIRST, None, (bool,)), 42 } 43 44 def __init__(self): 45 """ 46 Init container 47 @param view_type as ViewType, will be appended to any created view 48 """ 49 Gtk.Overlay.__init__(self) 50 NotificationContainer.__init__(self) 51 ScannerContainer.__init__(self) 52 PlaylistsContainer.__init__(self) 53 ViewsContainer.__init__(self) 54 55 def setup(self): 56 """ 57 Setup container 58 """ 59 self.__widget = Handy.Leaflet() 60 self.__widget.show() 61 self.__widget.connect("notify::folded", self.__on_folded) 62 self.__sub_widget = Handy.Leaflet() 63 self.__sub_widget.show() 64 self.__focused_view = None 65 self._stack = StackContainer() 66 self._stack.show() 67 ListsContainer.__init__(self) 68 self.__progress = ProgressBar() 69 self.__progress.get_style_context().add_class("progress-bottom") 70 self.__progress.set_property("valign", Gtk.Align.END) 71 self.add_overlay(self.__progress) 72 search_action = App().lookup_action("search") 73 search_action.connect("activate", self.__on_search_activate) 74 self.__widget.add(self.sidebar) 75 self.__grid_view = Grid() 76 self.__grid_view.set_orientation(Gtk.Orientation.VERTICAL) 77 self.__grid_view.show() 78 self.__sub_widget.add(self.left_list) 79 self.__sub_widget.add(self.__grid_view) 80 self.__grid_view.attach(self._stack, 0, 0, 1, 1) 81 self.__widget.add(self.__sub_widget) 82 self.__widget.set_visible_child(self.__sub_widget) 83 self.__sub_widget.set_visible_child(self.__grid_view) 84 self.add(self.__widget) 85 FilterContainer.__init__(self) 86 87 def stop(self): 88 """ 89 Stop current view from processing 90 """ 91 view = self._stack.get_visible_child() 92 if view is not None: 93 view.stop() 94 95 def reload_view(self): 96 """ 97 Reload current view 98 """ 99 view = self._stack.get_visible_child() 100 if view is not None and view.args is not None: 101 cls = view.__class__ 102 new_view = cls(**view.args) 103 new_view.populate() 104 new_view.show() 105 self._stack.add(new_view) 106 self._stack.set_visible_child(new_view) 107 else: 108 App().lookup_action("reload").change_state(GLib.Variant("b", True)) 109 110 def set_focused_view(self, view): 111 """ 112 Set focused view 113 @param view as View 114 """ 115 self.__focused_view = view 116 117 def go_home(self): 118 """ 119 Go back to first page 120 """ 121 self.__widget.set_visible_child(self.sidebar) 122 self._stack.clear() 123 emit_signal(self, "can-go-back-changed", False) 124 125 def go_back(self): 126 """ 127 Go back in history 128 """ 129 if self._stack.history.count > 0: 130 self._stack.go_back() 131 self.set_focused_view(self._stack.get_visible_child()) 132 elif self.__sub_widget.get_folded() and\ 133 self.__sub_widget.get_visible_child() != self.left_list: 134 self.__sub_widget.set_visible_child(self.left_list) 135 self._stack.clear() 136 elif self.__widget.get_folded() and\ 137 self.__widget.get_visible_child() != self.sidebar: 138 self.__widget.set_visible_child(self.sidebar) 139 self._stack.clear() 140 emit_signal(self, "can-go-back-changed", self.can_go_back) 141 142 @property 143 def can_go_back(self): 144 """ 145 True if can go back 146 @return bool 147 """ 148 if self.__widget.get_folded(): 149 return self.__widget.get_visible_child() != self._sidebar 150 else: 151 return self._stack.history.count > 0 152 153 @property 154 def widget(self): 155 """ 156 Get main widget 157 @return Handy.Leaflet 158 """ 159 return self.__widget 160 161 @property 162 def sub_widget(self): 163 """ 164 Get sub widget 165 @return Handy.Leaflet 166 """ 167 return self.__sub_widget 168 169 @property 170 def grid_view(self): 171 """ 172 Get grid view 173 @return Gtk.Grid 174 """ 175 return self.__grid_view 176 177 @property 178 def focused_view(self): 179 """ 180 Get focused view 181 @return View 182 """ 183 return self.__focused_view 184 185 @property 186 def view(self): 187 """ 188 Get current view 189 @return View 190 """ 191 view = self._stack.get_visible_child() 192 if view is not None and isinstance(view, View): 193 return view 194 return None 195 196 @property 197 def stack(self): 198 """ 199 Container stack 200 @return stack as Gtk.Stack 201 """ 202 return self._stack 203 204 @property 205 def progress(self): 206 """ 207 Progress bar 208 @return ProgressBar 209 """ 210 return self.__progress 211 212############ 213# PRIVATE # 214############ 215 def __on_folded(self, *ignore): 216 """ 217 Reload main view if needed 218 """ 219 if not App().window.folded and self.view is None: 220 self.show_view(self.sidebar.selected_ids) 221 222 def __on_search_activate(self, action, variant): 223 """ 224 @param action as Gio.SimpleAction 225 @param variant as GLib.Variant 226 """ 227 if App().window.folded: 228 search = variant.get_string() 229 App().window.container.show_view([Type.SEARCH], search) 230