diff --git a/Makefile b/Makefile index 9218056a5..2b0fc3272 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ mypy: # So give pyright a try. PYRIGHT_PKGS= PYRIGHT_PKGS+=feeluown/gui/uimain/sidebar.py +PYRIGHT_PKGS+=feeluown/gui/uimain/provider_bar.py pyright: pyright ${PYRIGHT_PKGS} diff --git a/feeluown/gui/drawers.py b/feeluown/gui/drawers.py index 6b38b345b..3813aa9da 100644 --- a/feeluown/gui/drawers.py +++ b/feeluown/gui/drawers.py @@ -468,3 +468,19 @@ def paint(self, painter): # Draw the fire shape painter.drawPath(path) + + +class EmojiIconDrawer: + def __init__(self, emoji: str, length: int, padding: int): + self._emoji = emoji + self._length = length + self._padding = padding + + def paint(self, painter: QPainter): + with painter_save(painter): + painter.translate(self._padding, self._padding) + width = self._length - 2 * self._padding + font = painter.font() + font.setPixelSize(width) + painter.setFont(font) + painter.drawText(0, 0, width, width, Qt.AlignCenter, self._emoji) diff --git a/feeluown/gui/provider_ui.py b/feeluown/gui/provider_ui.py index 7d7191555..e6714dd90 100644 --- a/feeluown/gui/provider_ui.py +++ b/feeluown/gui/provider_ui.py @@ -1,5 +1,8 @@ from abc import abstractmethod, ABC -from typing import TYPE_CHECKING, runtime_checkable, Protocol, Dict, Optional, List +from dataclasses import dataclass +from typing import ( + TYPE_CHECKING, runtime_checkable, Protocol, Dict, Optional, List, Callable, Any, +) from PyQt5.QtCore import pyqtSignal, QObject @@ -11,6 +14,13 @@ from feeluown.app.gui_app import GuiApp +@dataclass +class NavBtn: + icon: str + text: str + cb: Callable[[], Any] + + @runtime_checkable class UISupportsLoginOrGoHome(Protocol): @@ -44,6 +54,28 @@ def discovery(self): ... +@runtime_checkable +class UISupportsNavBtns(Protocol): + """ + Provider UI can add its own navigation buttons to the sidebar. + """ + + @abstractmethod + def list_nav_btns(self) -> List[NavBtn]: + ... + + +@runtime_checkable +class UISupportsCreatePlaylist(Protocol): + """ + Provider UI can create playlist. + """ + + @abstractmethod + def create_playlist(self): + ... + + class AbstractProviderUi(ABC): """Abstract base class for provider ui.""" diff --git a/feeluown/gui/uimain/provider_bar.py b/feeluown/gui/uimain/provider_bar.py index f5d28014f..d1d129cff 100644 --- a/feeluown/gui/uimain/provider_bar.py +++ b/feeluown/gui/uimain/provider_bar.py @@ -8,17 +8,14 @@ from feeluown.excs import ProviderIOError, NoUserLoggedIn from feeluown.library import ( - SupportsPlaylistDelete, - SupportsPlaylistCreateByName, - SupportsCurrentUser, + SupportsPlaylistDelete, SupportsPlaylistCreateByName, SupportsCurrentUser, ) from feeluown.utils import aio +from feeluown.gui.provider_ui import UISupportsNavBtns, UISupportsCreatePlaylist from feeluown.gui.components import Avatar from feeluown.gui.widgets import ( - DiscoveryButton, - StarButton, - PlusButton, - TriagleButton, + DiscoveryButton, StarButton, PlusButton, TriagleButton, + EmojiButton, ) from feeluown.gui.widgets.playlists import PlaylistsView from feeluown.gui.widgets.my_music import MyMusicView @@ -142,18 +139,34 @@ def setup_ui(self): self.discovery_btn.setToolTip('当前资源提供方未知') self.fold_top_btn.setToolTip('折叠/打开“主页和本地收藏集”功能') - def add_btn(self, btn): - self._btn_layout.addWidget(btn) - def on_current_pvd_ui_changed(self, pvd_ui, _): + self._clear_btns() if pvd_ui: self.discovery_btn.setEnabled(True) self.fav_btn.setEnabled(True) self.discovery_btn.setToolTip(f'点击进入 {pvd_ui.provider.name} 推荐页') + if isinstance(pvd_ui, UISupportsNavBtns): + for btn in pvd_ui.list_nav_btns(): + qt_btn = EmojiButton(btn.icon, btn.text, height=30, parent=self) + qt_btn.clicked.connect(btn.cb) + self._add_btn(qt_btn) + + if isinstance(pvd_ui, UISupportsCreatePlaylist): + self.playlists_con.create_btn.show() + self.playlists_con.create_btn.clicked.connect(pvd_ui.create_playlist) + else: + self.playlists_con.create_btn.hide() else: self.discovery_btn.setEnabled(False) self.fav_btn.setEnabled(False) + def _add_btn(self, btn): + self._btn_layout.addWidget(btn) + + def _clear_btns(self): + for btn in self._btn_layout.children(): + btn.deleteLater() + def _create_playlist(self): provider_ui = self._app.current_pvd_ui_mgr.get() if provider_ui is None: diff --git a/feeluown/gui/uimain/sidebar.py b/feeluown/gui/uimain/sidebar.py index 1ae839613..e8e5e3a69 100644 --- a/feeluown/gui/uimain/sidebar.py +++ b/feeluown/gui/uimain/sidebar.py @@ -2,9 +2,10 @@ from typing import TYPE_CHECKING from PyQt5.QtCore import QSize, Qt -from PyQt5.QtWidgets import (QFrame, QLabel, QVBoxLayout, QScrollArea, - QFormLayout, QDialog, QLineEdit, QDialogButtonBox, - QMessageBox) +from PyQt5.QtWidgets import ( + QFrame, QLabel, QVBoxLayout, QScrollArea, QMessageBox, + QFormLayout, QDialog, QLineEdit, QDialogButtonBox, +) from feeluown.collection import CollectionAlreadyExists, CollectionType from feeluown.utils.reader import create_reader, Reader @@ -69,8 +70,7 @@ def __init__(self, app: 'GuiApp', parent=None): '新建 fuo 文件,则可以新建收藏集,文件名即是收藏集的名字。\n\n' '手动编辑 fuo 文件即可编辑收藏集中的音乐资源,也可以在界面上拖拽来增删歌曲。') self.collections_view = CollectionListView(self._app) - self.collections_con = LVC(self.collections_header, - self.collections_view) + self.collections_con = LVC(self.collections_header, self.collections_view) self._top_separator = Separator(self._app) self.provider_bar = ProviderBar(self._app) diff --git a/feeluown/gui/widgets/__init__.py b/feeluown/gui/widgets/__init__.py index 3dea0451f..3e31f0963 100644 --- a/feeluown/gui/widgets/__init__.py +++ b/feeluown/gui/widgets/__init__.py @@ -6,5 +6,5 @@ PlusButton, TriagleButton, DiscoveryButton, SelfPaintAbstractIconTextButton, CalendarButton, RankButton, StarButton, PlayPauseButton, PlayNextButton, PlayPreviousButton, - MVButton, VolumeButton, HotButton, + MVButton, VolumeButton, HotButton, EmojiButton ) diff --git a/feeluown/gui/widgets/selfpaint_btn.py b/feeluown/gui/widgets/selfpaint_btn.py index e8db69c8f..ae55972b0 100644 --- a/feeluown/gui/widgets/selfpaint_btn.py +++ b/feeluown/gui/widgets/selfpaint_btn.py @@ -12,6 +12,7 @@ VolumeIconDrawer, SearchIconDrawer, FireIconDrawer, + EmojiIconDrawer, ) from feeluown.gui.helpers import darker_or_lighter, painter_save @@ -353,6 +354,15 @@ def draw_icon(self, painter): self.hot_icon.paint(painter) +class EmojiButton(SelfPaintAbstractIconTextButton): + def __init__(self, emoji: str, text='表情', *args, **kwargs): + super().__init__(text, *args, **kwargs) + self.emoji_icon = EmojiIconDrawer(emoji, self.height(), self._padding) + + def draw_icon(self, painter): + self.emoji_icon.paint(painter) + + class PlayButton(SelfPaintAbstractSquareButton): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)