• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

feeluown / FeelUOwn / 13067922984

31 Jan 2025 06:54AM UTC coverage: 56.468% (-0.3%) from 56.733%
13067922984

Pull #899

github

web-flow
Merge acce92d2d into d9f39dc04
Pull Request #899: [feat](*): AI based radio

72 of 186 new or added lines in 8 files covered. (38.71%)

5 existing lines in 1 file now uncovered.

10027 of 17757 relevant lines covered (56.47%)

0.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.88
/feeluown/gui/widgets/settings.py
1
from PyQt5.QtCore import pyqtSignal
1✔
2
from PyQt5.QtWidgets import QDialog, QWidget, QCheckBox, \
1✔
3
    QVBoxLayout, QHBoxLayout, QPlainTextEdit, QPushButton
4

5
from feeluown.gui.widgets.magicbox import KeySourceIn
1✔
6
from feeluown.gui.widgets.header import MidHeader
1✔
7
from feeluown.gui.components import LyricButton, WatchButton
1✔
8

9

10
class _ProviderCheckBox(QCheckBox):
1✔
11
    def set_identifier(self, identifier):
1✔
12
        self.identifier = identifier  # pylint: disable=W0201
×
13

14

15
class SearchProvidersFilter(QWidget):
1✔
16
    checked_btn_changed = pyqtSignal(list)
1✔
17

18
    def __init__(self, providers):
1✔
19
        super().__init__()
×
20
        self.providers = providers
×
21

22
        self._btns = []
×
23
        self._layout = QHBoxLayout(self)
×
24

25
        for provider in self.providers:
×
26
            btn = _ProviderCheckBox(provider.name, self)
×
27
            btn.set_identifier(provider.identifier)
×
28
            btn.clicked.connect(self.on_btn_clicked)
×
29
            self._layout.addWidget(btn)
×
30
            self._btns.append(btn)
×
31

32
        # HELP: we add spacing between checkboxes because they
33
        # will overlay each other on macOS by default. Why?
34
        self._layout.setSpacing(10)
×
35
        self._layout.addStretch(0)
×
36

37
    def get_checked_providers(self):
1✔
38
        identifiers = []
×
39
        for btn in self._btns:
×
40
            if btn.isChecked():
×
41
                identifiers.append(btn.identifier)
×
42
        return identifiers
×
43

44
    def set_checked_providers(self, providers):
1✔
45
        for provider in providers:
×
46
            for btn in self._btns:
×
47
                if provider == btn.identifier:
×
48
                    btn.setChecked(True)
×
49
                    break
×
50

51
    def on_btn_clicked(self, _):
1✔
52
        self.checked_btn_changed.emit(self.get_checked_providers())
×
53

54

55
class PlayerSettings(QWidget):
1✔
56
    def __init__(self, app, *args, **kwargs):
1✔
57
        super().__init__(*args, **kwargs)
×
58

59
        self._app = app
×
60
        self.lyric_btn = LyricButton(app, height=16)
×
61
        self.watch_btn = WatchButton(app, height=16)
×
62
        self._layout = QHBoxLayout(self)
×
63
        self._layout.addWidget(self.lyric_btn)
×
64
        self._layout.addWidget(self.watch_btn)
×
65
        self._layout.addStretch(0)
×
66

67

68
class AISettings(QWidget):
1✔
69
    def __init__(self, app, *args, **kwargs):
1✔
NEW
70
        super().__init__(*args, **kwargs)
×
71

NEW
72
        self._app = app
×
NEW
73
        self._prompt_editor = QPlainTextEdit(self)
×
NEW
74
        self._save_btn = QPushButton('保存', self)
×
75

NEW
76
        self._layout = QHBoxLayout(self)
×
NEW
77
        self._layout.addWidget(self._prompt_editor)
×
NEW
78
        self._layout.addWidget(self._save_btn)
×
NEW
79
        self._prompt_editor.setPlainText(self._app.config.AI_RADIO_PROMPT)
×
NEW
80
        self._prompt_editor.setMaximumHeight(200)
×
81

NEW
82
        self._save_btn.clicked.connect(self.save_prompt)
×
83

84
    def save_prompt(self):
1✔
NEW
85
        self._app.config.AI_RADIO_PROMPT = self._prompt_editor.toPlainText()
×
86

87

88
class SettingsDialog(QDialog):
1✔
89
    def __init__(self, app, parent=None):
1✔
90
        super().__init__(parent=parent)
×
91
        self._app = app
×
92

93
        self.setWindowTitle('应用配置')
×
94
        self.render()
×
95

96
    def render(self):
1✔
97
        source_in_str = self._app.browser.local_storage.get(KeySourceIn)
×
98
        if source_in_str is not None:
×
99
            source_in = source_in_str.split(',')
×
100
        else:
101
            source_in = [p.identifier for p in self._app.library.list()]
×
102
        toolbar = SearchProvidersFilter(self._app.library.list())
×
103
        toolbar.set_checked_providers(source_in)
×
104
        toolbar.checked_btn_changed.connect(self.update_source_in)
×
105

106
        self._layout = QVBoxLayout(self)
×
107
        self._layout.addWidget(MidHeader('搜索来源'))
×
108
        self._layout.addWidget(toolbar)
×
NEW
109
        self._layout.addWidget(MidHeader('AI 电台(PROMPT)'))
×
NEW
110
        self._layout.addWidget(AISettings(self._app))
×
111
        self._layout.addWidget(MidHeader('播放器'))
×
112
        self._layout.addWidget(PlayerSettings(self._app))
×
113
        self._layout.addStretch(0)
×
114

115
    def update_source_in(self, source_in):
1✔
116
        self._app.browser.local_storage[KeySourceIn] = ','.join(source_in)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc