diff --git a/feeluown/gui/browser.py b/feeluown/gui/browser.py index a36a1f7a08..548f5d8a4f 100644 --- a/feeluown/gui/browser.py +++ b/feeluown/gui/browser.py @@ -194,6 +194,8 @@ def initialize(self): from feeluown.gui.pages.provider_home import render as render_provider_home from feeluown.gui.pages.recently_played import render as render_recently_played from feeluown.gui.pages.recommendation import render as render_rec + from feeluown.gui.pages.recommendation_daily_songs import \ + render as render_rec_daily_songs model_prefix = f'{MODEL_PAGE_PREFIX}' @@ -211,6 +213,7 @@ async def dummy_render(req, *args, **kwargs): ('/recently_played', render_recently_played), ('/search', render_search), ('/rec', render_rec), + ('/rec/daily_songs', render_rec_daily_songs), ] for url, renderer in urlpatterns: self.route(url)(renderer) diff --git a/feeluown/gui/drawers.py b/feeluown/gui/drawers.py index 2336352ab2..49a448e88d 100644 --- a/feeluown/gui/drawers.py +++ b/feeluown/gui/drawers.py @@ -210,3 +210,48 @@ def paint(self, painter): painter.drawLine(self._body_bottom_left, self._body_bottom_right) painter.drawLine(self._body_top_left, self._body_bottom_left) painter.drawLine(self._body_top_right, self._body_bottom_right) + + +class CalendarIconDrawer: + def __init__(self, length, padding): + self._body_x = self._body_y = padding + self._body_width = length - 2 * padding + self._radius = 3 + self._h_line_y = self._body_y + self._body_width // 4 + + def paint(self, painter: QPainter): + pen = painter.pen() + pen.setWidthF(1.5) + painter.setPen(pen) + body_rect = QRect(self._body_x, self._body_x, self._body_width, self._body_width) + painter.drawRoundedRect(body_rect, self._radius, self._radius) + painter.drawLine(QPoint(self._body_x, self._h_line_y), + QPoint(self._body_x + self._body_width, self._h_line_y)) + + +class RankIconDrawer: + def __init__(self, length, padding): + body = length - 2*padding + body_2 = body // 2 + body_8 = body // 8 + body_3 = body // 3 + _top_right_x = length - padding + _top_right_y = padding + body_8 + _bottom_left_y = padding + body - body_8 + + self.p1 = QPoint(padding, _bottom_left_y) + self.p2 = QPoint(padding + body_3, padding + body_3) + self.p3 = QPoint(padding + body_2, padding + body_3 * 2) + self.p4 = QPoint(_top_right_x, _top_right_y) + self.p5 = QPoint(_top_right_x - body_3, _top_right_y) + self.p6 = QPoint(_top_right_x, _top_right_y + body_3) + + def paint(self, painter: QPainter): + pen = painter.pen() + pen.setWidthF(1.5) + painter.setPen(pen) + painter.drawLine(self.p1, self.p2) + painter.drawLine(self.p2, self.p3) + painter.drawLine(self.p3, self.p4) + painter.drawLine(self.p4, self.p5) + painter.drawLine(self.p4, self.p6) diff --git a/feeluown/gui/pages/recommendation.py b/feeluown/gui/pages/recommendation.py index a296291c71..1336fef90a 100644 --- a/feeluown/gui/pages/recommendation.py +++ b/feeluown/gui/pages/recommendation.py @@ -1,7 +1,7 @@ from typing import TYPE_CHECKING from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QWidget, QVBoxLayout +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout from feeluown.utils.reader import create_reader from feeluown.utils.aio import run_fn @@ -11,16 +11,10 @@ PlaylistCardListDelegate, ) -from feeluown.library import SupportsRecListDailyPlaylists, SupportsRecListDailySongs -from feeluown.gui.widgets.textbtn import TextButton -from feeluown.gui.helpers import fetch_cover_wrapper, BgTransparentMixin -from feeluown.gui.widgets.song_minicard_list import ( - SongMiniCardListView, - SongMiniCardListModel, - SongMiniCardListDelegate, -) +from feeluown.library import SupportsRecListDailyPlaylists -from fuo_netease import provider +from feeluown.gui.widgets import CalendarButton, RankButton +from feeluown.gui.helpers import fetch_cover_wrapper if TYPE_CHECKING: @@ -42,42 +36,41 @@ def __init__(self, app: 'GuiApp'): self.header_title = LargeHeader() self.header_playlist_list = MidHeader() - self.header_daily_rec = MidHeader() self.playlist_list_view = PlaylistCardListView(fixed_row_count=1) self.playlist_list_view.setItemDelegate( PlaylistCardListDelegate(self.playlist_list_view, card_min_width=100,)) - - self.daily_rec_view = SongMiniCardListView(no_scroll_v=False, fixed_row_count=2) - delegate = SongMiniCardListDelegate( - self.daily_rec_view, - card_min_width=150, - card_height=40, - card_padding=(5 + SongMiniCardListDelegate.img_padding, 5, 0, 5), - card_right_spacing=10, - ) - self.daily_rec_view.setItemDelegate(delegate) + self.daily_songs_btn = CalendarButton('每日推荐', parent=self) + self.rank_btn = RankButton(parent=self) + self.daily_songs_btn.setMinimumWidth(150) + self.rank_btn.setMinimumWidth(150) self.header_title.setText('发现音乐') self.header_playlist_list.setText('个性化推荐') - self.header_daily_rec.setText('每日推荐') self._layout = QVBoxLayout(self) self._setup_ui() - self.daily_rec_view.play_song_needed.connect(self._app.playlist.play_model) self.playlist_list_view.show_playlist_needed.connect( - lambda model: self.browser.goto(model=model)) + lambda model: self._app.browser.goto(model=model)) + self.daily_songs_btn.clicked.connect( + lambda: self._app.browser.goto(page='/rec/daily_songs')) + self.rank_btn.clicked.connect( + lambda: self._app.show_msg('未实现,欢迎 PR!')) def _setup_ui(self): + self._h_layout = QHBoxLayout() + self._h_layout.addWidget(self.daily_songs_btn) + self._h_layout.addSpacing(10) + self._h_layout.addWidget(self.rank_btn) + self._h_layout.addStretch(0) + self._layout.setContentsMargins(20, 10, 20, 0) self._layout.setSpacing(0) self._layout.addWidget(self.header_title) self._layout.addSpacing(10) - self._layout.addWidget(self.header_daily_rec) - self._layout.addSpacing(5) - self._layout.addWidget(self.daily_rec_view) - self._layout.addSpacing(10) + self._layout.addLayout(self._h_layout) + self._layout.addSpacing(30) self._layout.addWidget(self.header_playlist_list) self._layout.addSpacing(10) self._layout.addWidget(self.playlist_list_view) @@ -99,9 +92,3 @@ async def render(self): filter_model = PlaylistFilterProxyModel() filter_model.setSourceModel(model) self.playlist_list_view.setModel(filter_model) - - if isinstance(provider, SupportsRecListDailySongs): - songs = await run_fn(provider.rec_list_daily_songs) - model = SongMiniCardListModel(create_reader(songs), - fetch_cover_wrapper(self._app)) - self.daily_rec_view.setModel(model) diff --git a/feeluown/gui/pages/recommendation_daily_songs.py b/feeluown/gui/pages/recommendation_daily_songs.py new file mode 100644 index 0000000000..fd08cb1952 --- /dev/null +++ b/feeluown/gui/pages/recommendation_daily_songs.py @@ -0,0 +1,30 @@ +from typing import TYPE_CHECKING + +from feeluown.library import SupportsRecListDailySongs +from feeluown.gui.page_containers.table import TableContainer, Renderer +from feeluown.gui.page_containers.scroll_area import ScrollArea +from feeluown.utils.aio import run_fn +from feeluown.utils.reader import create_reader + + +if TYPE_CHECKING: + from feeluown.app.gui_app import GuiApp + + +async def render(req, **kwargs): + app: 'GuiApp' = req.ctx['app'] + pvd_ui = app.current_pvd_ui_mgr.get() + assert pvd_ui is not None + provider = pvd_ui.provider + + scroll_area = ScrollArea() + body = TableContainer(app, scroll_area) + scroll_area.setWidget(body) + app.ui.right_panel.set_body(scroll_area) + if isinstance(provider, SupportsRecListDailySongs): + songs = await run_fn(provider.rec_list_daily_songs) + renderer = Renderer() + await body.set_renderer(renderer) + renderer.show_songs(create_reader(songs)) + renderer.meta_widget.show() + renderer.meta_widget.title = f'每日推荐歌曲({provider.name})' diff --git a/feeluown/gui/widgets/__init__.py b/feeluown/gui/widgets/__init__.py index 437a349604..690815aecd 100644 --- a/feeluown/gui/widgets/__init__.py +++ b/feeluown/gui/widgets/__init__.py @@ -4,4 +4,5 @@ SelfPaintAbstractSquareButton, RecentlyPlayedButton, HomeButton, LeftArrowButton, RightArrowButton, SearchButton, SettingsButton, PlusButton, TriagleButton, DiscoveryButton, + SelfPaintAbstractIconTextButton, CalendarButton, RankButton, ) diff --git a/feeluown/gui/widgets/selfpaint_btn.py b/feeluown/gui/widgets/selfpaint_btn.py index 1bd5537024..a1b906f25d 100644 --- a/feeluown/gui/widgets/selfpaint_btn.py +++ b/feeluown/gui/widgets/selfpaint_btn.py @@ -2,7 +2,10 @@ from PyQt5.QtWidgets import QPushButton, QStyle, QStyleOptionButton from PyQt5.QtGui import QPainter, QPalette, QPainterPath -from feeluown.gui.drawers import HomeIconDrawer, PlusIconDrawer, TriangleIconDrawer +from feeluown.gui.drawers import ( + HomeIconDrawer, PlusIconDrawer, TriangleIconDrawer, CalendarIconDrawer, + RankIconDrawer, +) from feeluown.gui.helpers import darker_or_lighter @@ -275,6 +278,24 @@ def draw_icon(self, painter): self.home_icon.paint(painter) +class CalendarButton(SelfPaintAbstractIconTextButton): + def __init__(self, text='日历', *args, **kwargs): + super().__init__(text, *args, **kwargs) + self.calendar_icon = CalendarIconDrawer(self.height(), self._padding) + + def draw_icon(self, painter): + self.calendar_icon.paint(painter) + + +class RankButton(SelfPaintAbstractIconTextButton): + def __init__(self, text='排行榜', *args, **kwargs): + super().__init__(text, *args, **kwargs) + self.rank_icon = RankIconDrawer(self.height(), self._padding) + + def draw_icon(self, painter): + self.rank_icon.paint(painter) + + if __name__ == '__main__': from feeluown.gui.debug import simple_layout @@ -292,3 +313,5 @@ def draw_icon(self, painter): layout.addWidget(DiscoveryButton(height=length)) layout.addWidget(TriagleButton(length=length, direction='up')) + layout.addWidget(CalendarButton(height=length)) + layout.addWidget(RankButton(height=length))