Esempio n. 1
0
 def remove_song(self, song):
     # FIXME: this may block the whole app.
     if self._app.library.playlist_remove_song(self.playlist, song) is True:
         # Re-render songs table so that user can see that the song is removed.
         aio.run_afn(self._show_songs)
     else:
         self._app.show_msg('移除歌曲失败')
Esempio n. 2
0
    def show_current_user(self):
        """
        please ensure user is logged in
        """
        user = provider._user
        self._app.ui.left_panel.my_music_con.hide()
        self._app.ui.left_panel.playlists_con.show()
        self._app.ui.left_panel.my_music_con.show()

        mymusic_explore_item = self._app.mymusic_uimgr.create_item('🎵 发现音乐')
        mymusic_explore_item.clicked.connect(
            lambda: self._app.browser.goto(page='/providers/qqmusic/explore'),
            weak=False)
        mymusic_fav_item = self._app.mymusic_uimgr.create_item('♥ 收藏与关注')
        mymusic_fav_item.clicked.connect(
            lambda: self._app.browser.goto(page='/providers/qqmusic/fav'),
            weak=False)

        self._app.mymusic_uimgr.clear()
        self._app.mymusic_uimgr.add_item(mymusic_explore_item)
        # self._app.mymusic_uimgr.add_item(mymusic_rec_item)
        self._app.mymusic_uimgr.add_item(mymusic_fav_item)

        async def _show_playlists():
            playlists = await aio.run_fn(lambda: user.playlists)
            fav_playlists = await aio.run_fn(lambda: user.fav_playlists)
            self._app.pl_uimgr.add(playlists)
            self._app.pl_uimgr.add(fav_playlists, is_fav=True)
            self._pvd_item.text = f'QQ 音乐 - {user.name}'

        self._app.pl_uimgr.clear()
        aio.run_afn(_show_playlists)
Esempio n. 3
0
    def run(self):
        super().run()

        # oncemain should be moved from feeluown/cli to feeluown/app,
        # However, it depends on cli logic temporarily. If there is
        # an common module for these cli logic, oncemain can be moved.
        from feeluown.cli import oncemain  # pylint: disable=cyclic-import

        aio.run_afn(oncemain, self)
Esempio n. 4
0
    def __init__(self, app, parent=None):
        super().__init__(parent)

        self._app = app
        self._renderer = None
        self._table = None  # current visible table
        self._tables = []

        self._extra = None
        self.toolbar = SongsTableToolbar()
        self.tabbar = TableTabBarV2()
        self.meta_widget = TableMetaWidget(parent=self)
        self.songs_table = SongsTableView(parent=self)
        self.albums_table = AlbumListView(parent=self)
        self.artists_table = ArtistListView(parent=self)
        self.videos_table = VideoListView(parent=self)
        self.playlists_table = PlaylistListView(parent=self)
        self.comments_table = CommentListView(parent=self)
        self.desc_widget = DescLabel(parent=self)

        self._tables.append(self.songs_table)
        self._tables.append(self.albums_table)
        self._tables.append(self.artists_table)
        self._tables.append(self.playlists_table)
        self._tables.append(self.videos_table)
        self._tables.append(self.comments_table)

        self.songs_table.play_song_needed.connect(
            lambda song: aio.run_afn(self.play_song, song))
        self.videos_table.play_video_needed.connect(
            self._app.playlist.play_model)

        def goto_model(model):
            self._app.browser.goto(model=model)

        for signal in [
                self.songs_table.show_artist_needed,
                self.songs_table.show_album_needed,
                self.albums_table.show_album_needed,
                self.artists_table.show_artist_needed,
                self.playlists_table.show_playlist_needed,
        ]:
            signal.connect(goto_model)

        self.toolbar.play_all_needed.connect(
            lambda: aio.run_afn(self.play_all))
        self.songs_table.add_to_playlist_needed.connect(
            self._add_songs_to_playlist)
        self.songs_table.about_to_show_menu.connect(
            self._songs_table_about_to_show_menu)
        self.songs_table.activated.connect(lambda index: aio.create_task(
            self._on_songs_table_activated(index)))

        self._setup_ui()
Esempio n. 5
0
def show_provider(req):
    from .ui import LibraryRenderer
    if hasattr(req, 'ctx'):
        app = req.ctx['app']
    else:
        app = req  # 兼容老版本
    app.pl_uimgr.clear()
    # app.playlists.add(provider.playlists)

    app.ui.left_panel.my_music_con.hide()
    app.ui.left_panel.playlists_con.hide()

    aio.run_afn(
        app.ui.table_container.set_renderer,
        LibraryRenderer(provider.songs, provider.albums, provider.artists))
Esempio n. 6
0
    async def _show_songs(self):
        artist = self.model
        reader = await aio.run_fn(self._app.library.artist_create_songs_rd,
                                  artist)

        async def cb():
            reader = await aio.run_fn(self._app.library.artist_create_songs_rd,
                                      artist)
            self.show_songs(reader=reader, show_count=True)

        self.tabbar.show_songs_needed.connect(lambda: aio.run_afn(cb))
        self.show_songs(reader=reader, show_count=True)
Esempio n. 7
0
    async def render(self):
        album = self.model
        tab_index = self.tab_index

        self.meta_widget.title = album.name
        self.meta_widget.creator = album.artists_name
        self.meta_widget.show()

        self.render_tab_bar()

        if tab_index == 0:
            self.show_desc(self.model.description)
        else:
            reader = create_reader(album.songs)
            self.meta_widget.songs_count = reader.count
            self.show_songs(reader)

        # fetch cover and description
        cover = album.cover
        if cover:
            aio.run_afn(self.show_cover, cover, reverse(album, '/cover'))
Esempio n. 8
0
    async def render(self):
        self.render_tabbar()
        self.meta_widget.show()
        self.meta_widget.title = '收藏与关注'

        if self.tab_id == Tab.songs:
            self.show_songs(await aio.run_fn(lambda: self._user.cloud_songs))
            dir_upload_btn = TextButton('上传目录', self.toolbar)
            dir_upload_btn.clicked.connect(
                lambda: aio.run_afn(self._upload_cloud_songs_bydir))
            self.toolbar.add_tmp_button(dir_upload_btn)
            upload_btn = TextButton('上传音乐', self.toolbar)
            upload_btn.clicked.connect(lambda: aio.run_afn(self._upload_cloud_songs))
            self.toolbar.add_tmp_button(upload_btn)
            refresh_btn = TextButton('刷新音乐', self.toolbar)
            refresh_btn.clicked.connect(self._refresh_cloud_songs)
            self.toolbar.add_tmp_button(refresh_btn)
        elif self.tab_id == Tab.albums:
            self.show_albums(await aio.run_fn(lambda: self._user.fav_albums))
        elif self.tab_id == Tab.artists:
            self.show_artists(await aio.run_fn(lambda: self._user.fav_artists))
        elif self.tab_id == Tab.playlists:
            self.show_playlists(await aio.run_fn(lambda: self._user.fav_djradio))
Esempio n. 9
0
    def apply(self, menu):

        app = self._app
        song = self._song

        def enter_song_radio(song):
            radio = SongRadio.create(app, song)
            app.fm.activate(radio.fetch_songs_func, reset=False)
            if app.playlist.current_song != song:
                app.playlist.clear()
                self._app.playlist.next()
                self._app.player.resume()
            else:
                for song in app.playlist.list().copy():
                    if song is not app.playlist.current_song:
                        app.playlist.remove(song)
                self._app.player.resume()

        def goto_song_explore(song):
            app.browser.goto(model=song, path='/explore')

        async def goto_song_album(song):
            song = await aio.run_fn(self._app.library.song_upgrade, song)
            album = await aio.run_fn(lambda: song.album)
            self._app.browser.goto(model=album)

        menu.hovered.connect(self.on_action_hovered)
        artist_menu = menu.addMenu('查看歌手')
        artist_menu.menuAction().setData({'artists': None, 'song': song})

        menu.addAction('查看专辑').triggered.connect(
            lambda: aio.run_afn(goto_song_album, song))
        menu.addAction('歌曲电台').triggered.connect(
            lambda: enter_song_radio(song))
        menu.addAction('歌曲详情').triggered.connect(
            lambda: goto_song_explore(song))
Esempio n. 10
0
async def render(req, **kwargs):  # pylint: disable=too-many-locals
    app = req.ctx['app']
    song = req.ctx['model']

    # TODO: Initialize the view with song object, and it should reduce
    # the code complexity.
    view = SongExploreView(app=app)
    app.ui.right_panel.set_body(view)

    # show song album cover
    song = await aio.run_fn(app.library.song_upgrade, song)

    # bind signals
    view.play_btn.clicked.connect(lambda: app.playlist.play_model(song))
    if app.library.check_flags_by_model(song, PF.web_url):

        async def copy_song_web_url():
            web_url = await aio.run_fn(app.library.song_get_web_url, song)
            app.show_msg(f'已经复制:{web_url}')
            QGuiApplication.clipboard().setText(web_url)

        view.copy_web_url_btn.clicked.connect(
            lambda: aio.run_afn(copy_song_web_url))
        # TODO: Open url in browser when alt key is pressed. Use
        # QDesktopServices.openUrl to open url in browser, and
        # you may use QGuiApplication::keyboardModifiers to check
        # if alt key is pressed.
        #
        # NOTE(cosven): Since switching from applications is inconvenience,
        # the default behaviour of button is url-copy instead of url-open.
    else:
        view.copy_web_url_btn.hide()

    view.header_label.setText(f'<h1>{song.title}</h1>')
    aio.create_task(view.album_info_label.show_song(song))

    if app.library.check_flags_by_model(song, PF.similar):
        songs = await aio.run_fn(app.library.song_list_similar, song)
        model = SongListModel(create_reader(songs))
        view.similar_songs_view.setModel(model)
    else:
        view.similar_songs_header.setText('<span>该提供方暂不支持查看相似歌曲,555</span>')

    if app.library.check_flags_by_model(song, PF.hot_comments):
        comments = await aio.run_fn(app.library.song_list_hot_comments, song)
        comments_reader = create_reader(comments)
        view.comments_view.setModel(CommentListModel(comments_reader))
    else:
        view.comments_header.setText('<span>该提供方暂不支持查看歌曲评论,555</span>')

    try:
        lyric = app.library.song_get_lyric(song)
    except NotSupported as e:
        logger.info('cant show lyric due to %s', str(e))
    else:
        if lyric is not None:
            ms_sentence_map = parse_lyric_text(lyric.content)
            sentences = []
            for _, sentence in sorted(ms_sentence_map.items(),
                                      key=lambda item: item[0]):
                sentences.append(sentence)
            view.lyric_label.set_lyric('\n'.join(sentences))

    # Show album cover in the end since it's an expensive CPU/IO operation.
    # FIXME: handle NotSupported exception
    if song.album is not None:
        album = await aio.run_fn(app.library.album_upgrade, song.album)
        aio.create_task(
            view.cover_label.show_cover(album.cover, reverse(album)))
Esempio n. 11
0
 def write_tag(self, filename, succeed):
     tag_info = self._tagger_map.pop(filename, None)
     if succeed and tag_info:
         file_path, tag_obj, cover_url = tag_info
         aio.run_afn(self.set_tag, file_path, tag_obj, cover_url)