Skip to content

Commit

Permalink
*: add a collection sys_pool (#722)
Browse files Browse the repository at this point in the history
  • Loading branch information
cosven authored Jul 30, 2023
1 parent 9199a31 commit f34afe1
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 25 deletions.
37 changes: 31 additions & 6 deletions feeluown/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
logger = logging.getLogger(__name__)

COLL_LIBRARY_IDENTIFIER = 'library'
COLL_POOL_IDENTIFIER = 'pool'
# for backward compat, we should never change these filenames
LIBRARY_FILENAME = f'{COLL_LIBRARY_IDENTIFIER}.fuo'
POOL_FILENAME = f'{COLL_POOL_IDENTIFIER}.fuo'
DEPRECATED_FUO_FILENAMES = (
'Songs.fuo', 'Albums.fuo', 'Artists.fuo', 'Videos.fuo'
)
Expand All @@ -33,6 +35,7 @@ class CollectionAlreadyExists(Exception):

class CollectionType(Enum):
sys_library = 16
sys_pool = 13

mixed = 8

Expand Down Expand Up @@ -70,6 +73,8 @@ def load(self):
self.name = name
if name == COLL_LIBRARY_IDENTIFIER:
self.type = CollectionType.sys_library
elif name == COLL_POOL_IDENTIFIER:
self.type = CollectionType.sys_pool
else:
self.type = CollectionType.mixed

Expand Down Expand Up @@ -127,6 +132,11 @@ def create_empty(cls, fpath, title=''):
f.write(tomlkit.dumps(doc))
f.write(TOML_DELIMLF)

coll = cls(fpath)
coll._loads_metadata(doc)
coll.type = CollectionType.mixed
return coll

def add(self, model):
"""add model to collection
Expand Down Expand Up @@ -213,10 +223,13 @@ def __init__(self, app):
self._library = app.library
self.default_dir = COLLECTIONS_DIR

self._id_coll_mapping: Dict[str, Collection] = {}
self._id_coll_mapping: Dict[int, Collection] = {}
self._sys_colls = {}

def get(self, identifier):
return self._id_coll_mapping.get(int(identifier), None)
if identifier in (CollectionType.sys_pool, CollectionType.sys_library):
return self._sys_colls[identifier]
return self._id_coll_mapping[int(identifier)]

def get_coll_library(self):
for coll in self._id_coll_mapping.values():
Expand Down Expand Up @@ -259,12 +272,24 @@ def _get_dirs(self, ):

def scan(self):
colls: List[Collection] = []
library_coll = None
for coll in self._scan():
if coll.type == CollectionType.sys_library:
library_coll = coll
continue
colls.append(coll)
self._sys_colls[CollectionType.sys_library] = coll
elif coll.type == CollectionType.sys_pool:
self._sys_colls[CollectionType.sys_pool] = coll
else:
colls.append(coll)

if CollectionType.sys_pool not in self._sys_colls:
pool_fpath = os.path.join(self.default_dir, POOL_FILENAME)
assert not os.path.exists(pool_fpath)
logger.info('Generating collection pool.')
coll = Collection.create_empty(pool_fpath, '想听')
self._sys_colls[CollectionType.sys_pool] = coll

pool_coll = self._sys_colls[CollectionType.sys_pool]
library_coll = self._sys_colls[CollectionType.sys_library]
colls.insert(0, pool_coll)
colls.insert(0, library_coll)
for collection in colls:
coll_id = collection.identifier
Expand Down
2 changes: 1 addition & 1 deletion feeluown/gui/components/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def data(self, index, role=Qt.DisplayRole):
item = self._items[row]
if role == Qt.DisplayRole:
icon = '◎ '
if item.type == CollectionType.sys_library:
if item.type in (CollectionType.sys_library, CollectionType.sys_pool):
icon = '◉ '
return icon + item.name
if role == Qt.ToolTipRole:
Expand Down
19 changes: 11 additions & 8 deletions feeluown/gui/uimain/sidebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from PyQt5.QtWidgets import QFrame, QLabel, QVBoxLayout, QSizePolicy, QScrollArea, \
QHBoxLayout, QFormLayout, QDialog, QLineEdit, QDialogButtonBox, QMessageBox

from feeluown.collection import CollectionAlreadyExists
from feeluown.collection import CollectionAlreadyExists, CollectionType
from feeluown.gui.widgets import (
RecentlyPlayedButton, HomeButton, PlusButton, TriagleButton,
DiscoveryButton, HomeButton, PlusButton, TriagleButton,
)
from feeluown.gui.widgets.playlists import PlaylistsView
from feeluown.gui.components import CollectionListView
Expand Down Expand Up @@ -94,8 +94,8 @@ def __init__(self, app: 'GuiApp', parent=None):
self._app = app

self.home_btn = HomeButton(height=30, parent=self)
self.recently_played_btn = RecentlyPlayedButton(height=30, parent=self)
self.collections_header = QLabel('本地收藏', self)
self.discovery_btn = DiscoveryButton(height=30, padding=0.2, parent=self)
self.collections_header = QLabel('本地收藏集', self)
self.collections_header.setToolTip(
'我们可以在本地建立『收藏集』来收藏自己喜欢的音乐资源\n\n'
'每个收藏集都以一个独立 .fuo 文件的存在,'
Expand Down Expand Up @@ -129,9 +129,9 @@ def __init__(self, app: 'GuiApp', parent=None):
self._layout.addLayout(self._top_layout)
self._layout.addLayout(self._sub_layout)

self._top_layout.addWidget(self.home_btn)
self._top_layout.addWidget(self.recently_played_btn)
self._top_layout.setContentsMargins(15, 16, 16, 0)
self._top_layout.addWidget(self.home_btn)
self._top_layout.addWidget(self.discovery_btn)
self._sub_layout.setContentsMargins(16, 8, 16, 0)
self._sub_layout.addWidget(self.collections_con)
self._sub_layout.addWidget(self.my_music_con)
Expand All @@ -148,8 +148,7 @@ def __init__(self, app: 'GuiApp', parent=None):
self.my_music_con.hide()

self.home_btn.clicked.connect(self.show_library)
self.recently_played_btn.clicked.connect(
lambda: self._app.browser.goto(page='/recently_played'))
self.discovery_btn.clicked.connect(self.show_pool)
self.playlists_view.show_playlist.connect(
lambda pl: self._app.browser.goto(model=pl))
self.collections_view.show_collection.connect(
Expand Down Expand Up @@ -189,6 +188,10 @@ def show_library(self):
coll_library = self._app.coll_mgr.get_coll_library()
self._app.browser.goto(page=f'/colls/{coll_library.identifier}')

def show_pool(self):
coll = self._app.coll_mgr.get(CollectionType.sys_pool)
self._app.browser.goto(page=f'/colls/{coll.identifier}')

def remove_coll(self, coll):
def do():
self._app.coll_mgr.remove(coll)
Expand Down
2 changes: 1 addition & 1 deletion feeluown/gui/widgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
from .selfpaint_btn import ( # noqa
SelfPaintAbstractSquareButton, RecentlyPlayedButton,
HomeButton, LeftArrowButton, RightArrowButton, SearchButton, SettingsButton,
PlusButton, TriagleButton
PlusButton, TriagleButton, DiscoveryButton,
)
54 changes: 48 additions & 6 deletions feeluown/gui/widgets/selfpaint_btn.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from PyQt5.QtCore import QPoint, Qt, QRect, QRectF
from PyQt5.QtCore import QPoint, Qt, QRect, QRectF, QTimer, QPointF
from PyQt5.QtWidgets import QPushButton, QStyle, QStyleOptionButton
from PyQt5.QtGui import QPainter, QPalette
from PyQt5.QtGui import QPainter, QPalette, QPainterPath

from feeluown.gui.drawers import HomeIconDrawer, PlusIconDrawer, TriangleIconDrawer
from feeluown.gui.helpers import darker_or_lighter
Expand Down Expand Up @@ -32,10 +32,10 @@ def paint_border_bg_when_hover(self, painter, radius=3):


class SelfPaintAbstractIconTextButton(SelfPaintAbstractButton):
def __init__(self, text, height=30, padding=0.25, parent=None):
def __init__(self, text='', height=30, padding=0.25, parent=None):
super().__init__(parent=parent)

self._padding = int(height * padding) if padding < 1 else padding
self._padding: int = int(height * padding if padding < 1 else padding)
self._text_width = self.fontMetrics().horizontalAdvance(text)
self._text = text

Expand Down Expand Up @@ -200,8 +200,8 @@ def paintEvent(self, _):


class RecentlyPlayedButton(SelfPaintAbstractIconTextButton):
def __init__(self, *args, **kwargs):
super().__init__('最近播放', *args, **kwargs)
def __init__(self, text='最近播放', **kwargs):
super().__init__(text, **kwargs)

def draw_icon(self, painter):
pen_width = 1.5
Expand All @@ -225,6 +225,47 @@ def draw_icon(self, painter):
painter.drawPoint(QPoint(self._padding, center))


class DiscoveryButton(SelfPaintAbstractIconTextButton):
def __init__(self, text='发现', **kwargs):
super().__init__(text=text, **kwargs)

self._timer = QTimer(self)

length = self.height()
self._half = length // 2
self._v1 = self._half - self._padding
self._v2 = self._v1 / 2.5

self._triagle = QPainterPath(QPointF(-self._v2, 0))
self._triagle.lineTo(QPointF(0, self._v1))
self._triagle.lineTo(QPointF(0, self._v2))
self._rotate = 0
self._rotate_mod = 360

self._timer.timeout.connect(self.on_timeout)
self._timer.start(30)

def on_timeout(self):
self._rotate = (self._rotate + 2) % self._rotate_mod
self.update()

def draw_icon(self, painter: QPainter):
opt = QStyleOptionButton()
self.initStyleOption(opt)

pen = painter.pen()
pen.setWidthF(1.5)
painter.setPen(pen)

painter.save()
painter.translate(self._half, self._half)
painter.rotate(self._rotate)
for ratio in range(4):
painter.rotate(90*ratio)
painter.drawPath(self._triagle)
painter.restore()


class HomeButton(SelfPaintAbstractIconTextButton):
def __init__(self, *args, **kwargs):
super().__init__('主页', *args, **kwargs)
Expand All @@ -248,5 +289,6 @@ def draw_icon(self, painter):
layout.addWidget(SettingsButton(length=length))
layout.addWidget(RecentlyPlayedButton(height=length))
layout.addWidget(HomeButton(height=length))
layout.addWidget(DiscoveryButton(height=length))

layout.addWidget(TriagleButton(length=length, direction='up'))
8 changes: 5 additions & 3 deletions tests/test_collection.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from feeluown.models.uri import ResolveFailed, ResolverNotFound, reverse
from feeluown.collection import Collection, CollectionManager, LIBRARY_FILENAME
from feeluown.collection import Collection, CollectionManager, LIBRARY_FILENAME, \
POOL_FILENAME


def test_collection_load(tmp_path, song, mocker):
Expand Down Expand Up @@ -160,9 +161,10 @@ def new_collection(path):
coll1 = new_collection(tmp_path / '1.fuo')
coll2 = new_collection(tmp_path / '2.fuo')
coll_library = new_collection(tmp_path / LIBRARY_FILENAME)
coll_pool = new_collection(tmp_path / POOL_FILENAME)

coll_mgr = CollectionManager(app_mock)
mocker.patch.object(CollectionManager, '_scan',
return_value=[coll1, coll_library, coll2])
return_value=[coll1, coll_library, coll_pool, coll2])
coll_mgr.scan()
assert list(coll_mgr.listall()) == [coll_library, coll1, coll2]
assert list(coll_mgr.listall()) == [coll_library, coll_pool, coll1, coll2]

0 comments on commit f34afe1

Please sign in to comment.