async def render(self): playlist = self.playlist # show playlist title self.meta_widget.show() self.meta_widget.title = playlist.name # show playlist song list with suppress(ProviderIOError): if playlist.meta.allow_create_songs_g: reader = wrap(playlist.create_songs_g()) else: songs = await async_run(lambda: playlist.songs) reader = wrap(songs) self.show_songs(reader=reader, show_count=True) # show playlist cover if playlist.cover: aio.create_task( self.show_cover(playlist.cover, reverse(playlist, '/cover'))) def remove_song(song): playlist.remove(song.identifier) self.songs_table.remove_song_func = remove_song self.tabbar.show_desc_needed.connect( lambda: aio.create_task(self._show_desc()))
async def render(req, **kwargs): """/search handler :type app: feeluown.app.App """ q = req.query.get('q', '') if not q: return tab_id = Tab(int(req.query.get('tab_id', Tab.songs.value))) source_in = req.query.get('source_in', None) if source_in is not None: source_in = source_in.split(',') else: source_in = None app = req.ctx['app'] ui = app.ui right_panel = ui.right_panel table_container = right_panel.table_container right_panel.set_body(right_panel.scrollarea) search_type, _ = TabidSearchMapping[tab_id] reader = wrap( app.library.a_search(q, source_in=source_in, type_in=search_type)) renderer = SearchResultRenderer(q, tab_id, reader, source_in=source_in) await table_container.set_renderer(renderer)
async def render(req, **kwargs): """/search handler :type app: feeluown.app.App """ q = req.query.get('q', '') if not q: return type_ = req.query.get('type', None) type_ = SearchType.parse(type_) if type_ else SearchType.so source_in = req.query.get('source_in', None) if source_in is not None: source_in = source_in.split(',') else: source_in = None app = req.ctx['app'] ui = app.ui right_panel = ui.right_panel table_container = right_panel.table_container right_panel.collection_container.hide() right_panel.scrollarea.show() reader = wrap(app.library.a_search(q, type_in=type_, source_in=source_in)) renderer = SearchResultRenderer(q, type_, reader, source_in=source_in) await table_container.set_renderer(renderer)
async def render(self): mapping = { SearchType.so: ('songs', self.show_songs, self.tabbar.show_songs_needed), SearchType.al: ('albums', self.show_albums, self.tabbar.show_albums_needed), SearchType.ar: ('artists', self.show_artists, self.tabbar.show_artists_needed), SearchType.pl: ('playlists', self.show_playlists, self.tabbar.show_playlists_needed), SearchType.vi: ('videos', self.show_videos, self.tabbar.show_videos_needed), } for search_type, (_, _, signal) in mapping.items(): signal.connect(self._show(search_type)) self.tabbar.show() self.tabbar.library_mode() self.tabbar.check(TypeTabMapping[self.type_]) self.meta_widget.show() self.meta_widget.title = '搜索 “{}”'.format(self.q) self.render_toolbar() attr, show_handler, signal = mapping[self.type_] async def models_g(): async for result in self.reader: if result is not None: for obj in (getattr(result, attr) or []): yield obj show_handler(reader=wrap(models_g()))
def _show_songs(self): """filter model with other type""" self.show_songs( wrap([ model for model in self.collection.models if model.meta.model_type == ModelType.song ]))
async def render(self): self.meta_widget.title = '当前播放列表' self.meta_widget.show() player = self._app.player playlist = player.playlist async def clear_playlist(): playlist.clear() await self.render() # re-render songs = playlist.list() self.show_songs(wrap(songs.copy())) btn = TextButton('清空', self.toolbar) btn.clicked.connect(lambda *args: aio.create_task(clear_playlist())) self.toolbar.add_tmp_button(btn) self.songs_table.remove_song_func = playlist.remove # scroll to current song current_song = self._app.playlist.current_song if current_song is not None: row = songs.index(current_song) model_index = self.songs_table.model().index(row, 0) self.songs_table.scrollTo(model_index) self.songs_table.selectRow(row)
def _show_pure_videos_coll(coll): from feeluown.gui.page_containers.table import VideosRenderer self.set_body(self.scrollarea) reader = wrap(coll.models) renderer = VideosRenderer(reader) aio.create_task(self.table_container.set_renderer(renderer))
async def render(self): artist = self.artist # bind signal first # we only show album that implements create_albums_g if artist.meta.allow_create_albums_g: self.toolbar.filter_albums_needed.connect( lambda types: self.albums_table.model().filter_by_types(types)) self.tabbar.show_albums_needed.connect( lambda: self.show_albums(self.artist.create_albums_g())) if hasattr(artist, 'contributed_albums') and artist.contributed_albums: # show contributed_album list self.tabbar.show_contributed_albums_needed.connect( lambda: self.show_albums(self.artist. create_contributed_albums_g())) # fetch and render basic metadata self.meta_widget.title = artist.name self.meta_widget.show() self.tabbar.show() self.tabbar.artist_mode() # fetch and render songs songs = songs_g = None if artist.meta.allow_create_songs_g: songs_g = wrap(artist.create_songs_g()) self.tabbar.show_songs_needed.connect( lambda: self.show_songs(songs_g=wrap(artist.create_songs_g()), songs=songs, show_count=True)) else: songs = await async_run(lambda: artist.songs) self.tabbar.show_songs_needed.connect(lambda: self.show_songs( songs_g=None, songs=songs, show_count=True)) self.show_songs(songs_g=songs_g, songs=songs, show_count=True) # finally, we render cover and description cover = await async_run(lambda: artist.cover) if cover: aio.create_task( self.show_cover(cover, reverse(artist, '/cover'), as_background=True)) self.tabbar.show_desc_needed.connect( lambda: aio.create_task(self._show_desc()))
async def render(self): self.meta_widget.show() self.tabbar.show() self.tabbar.library_mode() # render songs self.show_songs(reader=wrap(self.songs), show_count=True) # bind signals self.toolbar.filter_albums_needed.connect( lambda types: self.albums_table.model().filter_by_types(types)) self.tabbar.show_songs_needed.connect( lambda: self.show_songs(reader=wrap(self.songs), show_count=True)) self.tabbar.show_albums_needed.connect( lambda: self.show_albums(self.albums)) self.tabbar.show_artists_needed.connect( lambda: self.show_artists(self.artists))
def _show_pure_videos_coll(coll): from feeluown.containers.table import VideosRenderer self.collection_container.hide() self.scrollarea.show() reader = wrap(coll.models) renderer = VideosRenderer(reader) aio.create_task(self.table_container.set_renderer(renderer))
async def test_async_sequential_reader(): async def ag_func(): for i in range(0, 5): yield i ag = ag_func() reader = wrap(ag) assert reader.is_async is True assert len([x async for x in reader]) == 5
def show_songs(self, songs=None, songs_g=None): """(DEPRECATED) provided only for backward compatibility""" warnings.warn('use readerer.show_songs please') renderer = Renderer() task = aio.create_task(self.set_renderer(renderer)) if songs is not None: reader = wrap(songs) else: reader = songs_g task.add_done_callback(lambda _: renderer.show_songs(reader=reader))
def test_sequential_reader(): def g_func(): for i in range(0, 5): yield i g = g_func() reader = wrap(g) assert reader.is_async is False assert len(list(reader)) == 5
async def render(self): self.render_tabbar() self.meta_widget.show() self.meta_widget.title = '音乐库' coll = self._app.coll_uimgr.get_coll_library() mtype = self.get_tabid_mtype_mapping()[self.tab_id] models = [model for model in coll.models if model.meta.model_type == mtype] reader = wrap(models) show_handler = self.get_tabid_handler_mapping()[self.tab_id] show_handler(reader)
async def render(self): coll = self._coll self.meta_widget.show() if coll.type is CollectionType.sys_library: self.meta_widget.title = '音乐库' else: self.meta_widget.title = coll.name self.render_tab_bar() _, mtype, show_handler = self.tabs[self.tab_index] models = [model for model in coll.models if model.meta.model_type == mtype] reader = wrap(models) show_handler(reader)
async def render(req, **kwargs): app = req.ctx['app'] provider = app.library.get('netease') playlists = provider._user.rec_playlists view = ExploreView() model = PlaylistListModel(wrap(playlists), fetch_cover_wrapper( app.img_mgr), {p.identifier: p.name for p in app.library.list()}) filter_model = PlaylistFilterProxyModel() filter_model.setSourceModel(model) view.playlist_list_view.setModel(filter_model) view.playlist_list_view.show_playlist_needed.connect( lambda model: app.browser.goto(model=model)) app.ui.right_panel.set_body(view)
async def render(self): self.meta_widget.show() self.meta_widget.title = f'搜索 “{self.q}”' self.render_tab_bar() _, search_type, attrname, show_handler = self.tabs[self.tab_index] async def models_g(): async for result in self._app.library.a_search( self.q, source_in=self.source_in, type_in=search_type): if result is not None: for obj in (getattr(result, attrname) or []): yield obj show_handler(reader=wrap(models_g())) self.toolbar.hide()
async def show_album(self, album): meta_widget = self.collection_body.meta_widget meta_widget.clear() meta_widget.title = album.name_display meta_widget.creator = album.artists_name_display songs = await async_run(lambda: album.songs) meta_widget.songs_count = len(songs) reader = wrap(songs) model = SongListModel(reader) self.collection_body.song_list_view.show() self.collection_body.song_list_view.setModel(model) meta_widget.desc = await async_run(lambda: album.desc) meta_widget.title = await async_run(lambda: album.name) meta_widget.creator = await async_run(lambda: album.artists_name) cover = await async_run(lambda: album.cover) if cover: aio.create_task(self.show_cover(cover, reverse(album, '/cover')))
def __init__(self, reader, fetch_image, source_name_map=None, parent=None): """ :param reader: objects in reader should have `name` property :param fetch_image: func(item, cb, uid) :type reader: Iterable """ super().__init__(parent) self.source_name_map = source_name_map or {} self.reader = wrap(reader) self.fetch_image = fetch_image # false: no more, true: maybe more self._maybe_has_more = True self.items = [] self.colors = [] self.pixmaps = {} # {uri: QPixmap}
def __init__(self, reader, fetch_image, source_name_map=None, parent=None): """ :param reader: objects in reader should have `name` property :param fetch_image: func(item, cb, uid) :type reader: Iterable """ super().__init__(parent) self.reader = self._reader = wrap(reader) self._fetch_more_step = 10 self._items = [] self._is_fetching = False self.source_name_map = source_name_map or {} self.fetch_image = fetch_image self.colors = [] self.pixmaps = {} # {uri: QPixmap}
async def render(self): self.render_tabbar() self.meta_widget.show() self.meta_widget.title = '搜索 “{}”'.format(self.q) self.render_toolbar() show_handler = self.get_tabid_handler_mapping()[self.tab_id] _, attrname = TabidSearchMapping[self.tab_id] async def models_g(): async for result in self.reader: if result is not None: for obj in (getattr(result, attrname) or []): yield obj show_handler(reader=wrap(models_g()))
async def render(self): album = self.album songs = await async_run(lambda: album.songs) self.show_songs(wrap(songs)) self.meta_widget.title = album.name_display self.meta_widget.songs_count = len(songs) self.meta_widget.creator = album.artists_name_display self.meta_widget.show() # fetch cover and description cover = await async_run(lambda: album.cover) if cover: aio.create_task(self.show_cover(cover, reverse(album, '/cover'))) self.tabbar.show() self.tabbar.album_mode() self.tabbar.show_desc_needed.connect(lambda: aio.create_task(self._show_desc())) self.tabbar.show_songs_needed.connect(lambda: self.show_songs(songs))
def show_songs(self, reader, show_count=False): reader = wrap(reader) self.container.current_table = self.songs_table self.toolbar.show() if show_count: count = reader.count self.meta_widget.songs_count = -1 if count is None else count source_name_map = {p.identifier: p.name for p in self._app.library.list()} model = SongsTableModel( source_name_map=source_name_map, reader=reader, parent=self.songs_table) filter_model = SongFilterProxyModel(self.songs_table) filter_model.setSourceModel(model) self.songs_table.setModel(filter_model) self.songs_table.scrollToTop() disconnect_slots_if_has(self._app.ui.magicbox.filter_text_changed) self._app.ui.magicbox.filter_text_changed.connect(filter_model.filter_by_text)
def create_albums_g(self): return wrap(self.albums)
def create_contributed_albums_g(self): return wrap(self.contributed_albums)
def show_comments(self, comments): self.container.current_table = self.comments_table reader = wrap(comments) model = CommentListModel(reader) self.comments_table.setModel(model)
def __init__(self, source_name_map, playlist): reader = wrap(playlist.list()) super().__init__(source_name_map, reader) self._playlist = playlist
content = ('有没有一首歌会让你很想念,有没有一首歌你会假装听不见,' '听了又掉眼泪,却按不下停止健') brief_comment = BriefCommentModel(identifier='ouf', user_name='world', content='有没有人曾告诉你') comment = CommentModel( identifier='fuo', source='fuo', user=user, liked_count=1, content=content, time=int(time.time()), parent=brief_comment, ) comment2 = comment.copy() comment2.content = 'hello world' reader = wrap([comment, comment2] * 1000) QML_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'demo.qml') if __name__ == '__main__': app = QApplication([]) widget = QWidget() view = QQuickView() model = CommentListModel(reader) view.setInitialProperties({"model": model}) view.setSource(QUrl.fromLocalFile(QML_PATH)) container = widget.createWindowContainer(view) layout = QVBoxLayout(widget) layout.addWidget(container) widget.show() widget.resize(600, 400) app.exec()
if __name__ == '__main__': import time from PyQt5.QtWidgets import QApplication from feeluown.utils.reader import wrap from feeluown.library.models import CommentModel, BriefUserModel, BriefCommentModel user = BriefUserModel(identifier='fuo-bot', source='fuo', name='随风而去') content = ('有没有一首歌会让你很想念,有没有一首歌你会假装听不见,' '听了又掉眼泪,却按不下停止健') brief_comment = BriefCommentModel(identifier='ouf', user_name='world', content='有没有人曾告诉你') comment = CommentModel( identifier='fuo', source='fuo', user=user, liked_count=1, content=content, time=int(time.time()), parent=brief_comment, ) comment2 = comment.copy() comment2.content = 'hello world' app = QApplication([]) reader = wrap([comment, comment2, comment]) model = CommentListModel(reader) widget = CommentListView() widget.setModel(model) widget.show() app.exec()
def _show_pure_albums_coll(coll): self.set_body(self.scrollarea) reader = wrap(coll.models) self.table_container.show_albums_coll(reader)