style: format all code to PEP8 (flake8 clean)

Reformat every module with autopep8 and hand-tune the remaining long
lines so that `flake8` passes with default settings (max line length
79). No behavior changes: long f-strings, messages, QSS/Textual CSS
rules and argument lists are only wrapped or split, an unused import
and an unused local are dropped, and dbus-next D-Bus signature
annotations carry targeted `# noqa` comments.
This commit is contained in:
jads
2026-10-23 23:52:14 +03:00
parent 4460791a95
commit e71f5623a7
7 changed files with 558 additions and 213 deletions

205
qt_app.py
View File

@@ -111,7 +111,9 @@ QLabel { background: transparent; }
#albumLabel { color: #6f6f82; font-size: 12px; }
#timeLabel { color: #8b8b9e; font-size: 11px; }
#queueLabel { color: #6f6f82; font-size: 11px; }
QSlider::groove:horizontal { height: 4px; background: #2a2a36; border-radius: 2px; }
QSlider::groove:horizontal {
height: 4px; background: #2a2a36; border-radius: 2px;
}
QSlider::sub-page:horizontal { background: #ff3b5c; border-radius: 2px; }
QSlider::handle:horizontal {
width: 12px; margin: -4px 0; border-radius: 6px; background: #ffffff;
@@ -119,24 +121,32 @@ QSlider::handle:horizontal {
QSlider::handle:horizontal:hover { background: #ffd9df; }
#playBtn { background: #ff3b5c; border: none; border-radius: 38px; }
#playBtn:hover { background: #ff5574; }
#prevBtn, #nextBtn { background: rgba(255,255,255,0.05); border: none; border-radius: 22px; }
#prevBtn, #nextBtn {
background: rgba(255,255,255,0.05); border: none; border-radius: 22px;
}
#prevBtn:hover, #nextBtn:hover { background: rgba(255,255,255,0.11); }
#actionBtn {
background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08); border-radius: 16px;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(255,255,255,0.08); border-radius: 16px;
padding: 8px 18px; font-size: 12px;
}
#actionBtn:hover { background: rgba(255,255,255,0.09); }
#actionBtn[liked="true"] { color: #ff8296; border-color: rgba(255,59,92,0.40); }
#actionBtn[liked="true"] {
color: #ff8296; border-color: rgba(255,59,92,0.40);
}
#menuBtn:focus, #prevBtn:focus, #nextBtn:focus, #playBtn:focus,
#actionBtn:focus, #backBtn:focus, #searchBtn:focus {
border: 2px solid #ffffff;
}
QSlider:focus { border: 1px solid #ffffff; border-radius: 4px; }
#drawer { background: #16161f; border-right: 1px solid rgba(255,255,255,0.06); }
#drawer {
background: #16161f; border-right: 1px solid rgba(255,255,255,0.06);
}
#drawerTitle { font-size: 18px; font-weight: 700; padding: 4px 2px 10px 2px; }
#drawerBrand { color: #6f6f82; font-size: 11px; padding: 0 2px 12px 2px; }
#drawer QPushButton {
text-align: left; background: transparent; border: none; border-radius: 10px;
text-align: left; background: transparent;
border: none; border-radius: 10px;
padding: 11px 12px; font-size: 14px; color: #e8e8f0;
}
#drawer QPushButton:hover { background: rgba(255,255,255,0.06); }
@@ -151,7 +161,8 @@ QSlider:focus { border: 1px solid #ffffff; border-radius: 4px; }
QListWidget { background: transparent; border: none; outline: 0; }
QListWidget::item { border: none; }
QLineEdit {
background: #1b1b25; border: 1px solid rgba(255,255,255,0.07); border-radius: 13px;
background: #1b1b25; border: 1px solid rgba(255,255,255,0.07);
border-radius: 13px;
padding: 9px 12px; font-size: 14px; selection-background-color: #ff3b5c;
}
QLineEdit:focus { border-color: rgba(255,59,92,0.53); }
@@ -170,7 +181,8 @@ QComboBox QAbstractItemView {
QCheckBox { color: #dcdce6; font-size: 13px; spacing: 8px; }
QCheckBox::indicator { width: 16px; height: 16px; }
QCheckBox::indicator:unchecked {
border: 1px solid rgba(255,255,255,0.35); border-radius: 4px; background: #1b1b25;
border: 1px solid rgba(255,255,255,0.35);
border-radius: 4px; background: #1b1b25;
}
#searchBtn {
background: #ff3b5c; border: none; border-radius: 13px;
@@ -188,14 +200,16 @@ QScrollBar::handle:vertical {
QScrollBar::add-line, QScrollBar::sub-line { height: 0; }
QScrollBar::add-page, QScrollBar::sub-page { background: transparent; }
#toast {
background: #23232f; border: 1px solid rgba(255,255,255,0.09); border-radius: 14px;
background: #23232f; border: 1px solid rgba(255,255,255,0.09);
border-radius: 14px;
padding: 10px 16px; color: #f2f2f7; font-size: 12px;
}
"""
def media_icon(kind: str, size: int = 64) -> QIcon:
"""Рисует белые иконки плеера, чтобы они выглядели одинаково в любой теме."""
"""Рисует белые иконки плеера, чтобы они выглядели одинаково
в любой теме."""
pixmap = QPixmap(size, size)
pixmap.fill(Qt.GlobalColor.transparent)
painter = QPainter(pixmap)
@@ -211,10 +225,31 @@ def media_icon(kind: str, size: int = 64) -> QIcon:
path.closeSubpath()
painter.drawPath(path)
elif kind == "pause":
painter.drawRoundedRect(QRectF(20 * s, 16 * s, 9 * s, 32 * s), 2 * s, 2 * s)
painter.drawRoundedRect(QRectF(35 * s, 16 * s, 9 * s, 32 * s), 2 * s, 2 * s)
painter.drawRoundedRect(
QRectF(
20 * s,
16 * s,
9 * s,
32 * s),
2 * s,
2 * s)
painter.drawRoundedRect(
QRectF(
35 * s,
16 * s,
9 * s,
32 * s),
2 * s,
2 * s)
elif kind == "prev":
painter.drawRoundedRect(QRectF(15 * s, 14 * s, 7 * s, 36 * s), 2 * s, 2 * s)
painter.drawRoundedRect(
QRectF(
15 * s,
14 * s,
7 * s,
36 * s),
2 * s,
2 * s)
path = QPainterPath()
path.moveTo(52 * s, 14 * s)
path.lineTo(52 * s, 50 * s)
@@ -222,7 +257,14 @@ def media_icon(kind: str, size: int = 64) -> QIcon:
path.closeSubpath()
painter.drawPath(path)
elif kind == "next":
painter.drawRoundedRect(QRectF(42 * s, 14 * s, 7 * s, 36 * s), 2 * s, 2 * s)
painter.drawRoundedRect(
QRectF(
42 * s,
14 * s,
7 * s,
36 * s),
2 * s,
2 * s)
path = QPainterPath()
path.moveTo(12 * s, 14 * s)
path.lineTo(12 * s, 50 * s)
@@ -320,14 +362,14 @@ class CoverView(QWidget):
gradient.setColorAt(0.0, QColor("#252533"))
gradient.setColorAt(1.0, QColor("#15151d"))
painter.fillRect(rect, gradient)
painter.setPen(QColor(255,255,255,48))
painter.setPen(QColor(255, 255, 255, 48))
font = QFont()
font.setPointSize(64)
painter.setFont(font)
painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, "♪")
painter.setClipping(False)
painter.setPen(QPen(QColor(255,255,255,31), 1))
painter.setPen(QPen(QColor(255, 255, 255, 31), 1))
painter.setBrush(Qt.BrushStyle.NoBrush)
painter.drawRoundedRect(rect.adjusted(0.5, 0.5, -0.5, -0.5), 20, 20)
painter.end()
@@ -422,7 +464,12 @@ class TrackDelegate(QStyledItemDelegate):
painter.setPen(QColor("#6f6f82"))
painter.drawText(
QRectF(rect.right() - duration_width, rect.top(), duration_width, 22),
QRectF(
rect.right() -
duration_width,
rect.top(),
duration_width,
22),
Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter,
duration,
)
@@ -539,7 +586,8 @@ class QtMusicApp(QMainWindow):
self._update_cover_size()
self.play_btn.setFocus()
# MPRIS: система видит плеер как источник звука (панель GNOME, playerctl).
# MPRIS: система видит плеер как источник звука (панель GNOME,
# playerctl).
self.mpris_bridge = MprisBridge(self)
self.mpris_bridge.play.connect(self.mpris_play)
self.mpris_bridge.pause.connect(self.mpris_pause)
@@ -608,9 +656,12 @@ class QtMusicApp(QMainWindow):
)
self.pages.addWidget(self.wave_page)
self.search_page, self.search_input, self.search_list, self.search_status = (
self._build_search_page()
)
(
self.search_page,
self.search_input,
self.search_list,
self.search_status,
) = self._build_search_page()
self.search_list._queue_name = "Поиск"
self.search_list._tracks = []
self.search_list.itemDoubleClicked.connect(
@@ -618,9 +669,12 @@ class QtMusicApp(QMainWindow):
)
self.pages.addWidget(self.search_page)
self.lyrics_page, self.lyrics_title, self.lyrics_status, self.lyrics_body = (
self._build_lyrics_page()
)
(
self.lyrics_page,
self.lyrics_title,
self.lyrics_status,
self.lyrics_body,
) = self._build_lyrics_page()
self.pages.addWidget(self.lyrics_page)
self.settings_page = self._build_settings_page()
@@ -708,8 +762,10 @@ class QtMusicApp(QMainWindow):
self.slider.setRange(0, 0)
self.slider.seekRequested.connect(self.on_slider_seek)
self.slider.actionTriggered.connect(self.on_slider_action)
self.slider.scrubStarted.connect(lambda: setattr(self, "_seeking", True))
self.slider.scrubFinished.connect(lambda: setattr(self, "_seeking", False))
self.slider.scrubStarted.connect(
lambda: setattr(self, "_seeking", True))
self.slider.scrubFinished.connect(
lambda: setattr(self, "_seeking", False))
layout.addWidget(self.slider)
layout.addSpacing(3)
@@ -794,7 +850,8 @@ class QtMusicApp(QMainWindow):
row.addStretch(1)
return row
def _build_list_page(self, title: str) -> tuple[QWidget, QListWidget, QLabel]:
def _build_list_page(
self, title: str) -> tuple[QWidget, QListWidget, QLabel]:
page = QWidget()
layout = QVBoxLayout(page)
layout.setContentsMargins(16, 10, 16, 12)
@@ -813,7 +870,8 @@ class QtMusicApp(QMainWindow):
layout.addWidget(widget, 1)
return page, widget, status
def _build_search_page(self) -> tuple[QWidget, QLineEdit, QListWidget, QLabel]:
def _build_search_page(
self) -> tuple[QWidget, QLineEdit, QListWidget, QLabel]:
page = QWidget()
layout = QVBoxLayout(page)
layout.setContentsMargins(16, 10, 16, 12)
@@ -930,15 +988,21 @@ class QtMusicApp(QMainWindow):
self.start_combo.setObjectName("settingCombo")
for key in START_QUEUES:
self.start_combo.addItem(START_QUEUE_LABELS[key], key)
start_index = self.start_combo.findData(self.settings.get("start_queue", "wave"))
start_index = self.start_combo.findData(
self.settings.get("start_queue", "wave"))
self.start_combo.setCurrentIndex(max(0, start_index))
self.start_combo.currentIndexChanged.connect(self.on_start_changed)
start_row.addWidget(start_label)
start_row.addWidget(self.start_combo, 1)
layout.addLayout(start_row)
self.wave_check = QCheckBox("Продолжать «Мою волну» с последних треков")
self.wave_check.setChecked(bool(self.settings.get("wave_from_history", True)))
self.wave_check = QCheckBox(
"Продолжать «Мою волну» с последних треков")
self.wave_check.setChecked(
bool(
self.settings.get(
"wave_from_history",
True)))
self.wave_check.toggled.connect(self.on_wave_from_history_toggled)
layout.addWidget(self.wave_check)
@@ -1147,7 +1211,11 @@ class QtMusicApp(QMainWindow):
self.set_top_status("Загрузка…")
self.run_task(self._fetch_initial, self.apply_initial, self.on_error)
def _fetch_initial(self) -> tuple[str, list[dict], set[str], list[dict], str]:
def _fetch_initial(self) -> tuple[str,
list[dict],
set[str],
list[dict],
str]:
api = self.api
uid = self.uid or get_uid(api)
# Продолжаем волну с последних прослушанных треков, а не с начала.
@@ -1170,7 +1238,8 @@ class QtMusicApp(QMainWindow):
liked = {str(track.get("id")) for track in start}
else:
payload = api.get(f"/users/{uid}/likes/tracks")
refs = ((payload.get("result") or {}).get("library") or {}).get("tracks") or []
refs = ((payload.get("result") or {}).get(
"library") or {}).get("tracks") or []
liked = {str(ref.get("id")) for ref in refs}
if want == "history":
start, name = list(self.history), "История"
@@ -1214,14 +1283,17 @@ class QtMusicApp(QMainWindow):
def update_like_button(self, liked: bool | None = None) -> None:
if liked is None:
liked = bool(self.current and str(self.current.get("id")) in self.liked_ids)
liked = bool(
self.current and str(
self.current.get("id")) in self.liked_ids)
self.like_btn.setText("♥ В избранном" if liked else "♡ В избранное")
self.like_btn.setProperty("liked", "true" if liked else "false")
self.like_btn.style().unpolish(self.like_btn)
self.like_btn.style().polish(self.like_btn)
def update_play_button(self, *args) -> None:
playing = self.player.playbackState() == QMediaPlayer.PlaybackState.PlayingState
state = self.player.playbackState()
playing = state == QMediaPlayer.PlaybackState.PlayingState
self.play_btn.setIcon(media_icon("pause" if playing else "play", 80))
self._update_mpris_status()
@@ -1239,7 +1311,9 @@ class QtMusicApp(QMainWindow):
return
self.cover.set_pixmap(None)
request = QNetworkRequest(QUrl(url))
request.setHeader(QNetworkRequest.KnownHeaders.UserAgentHeader, USER_AGENT)
request.setHeader(
QNetworkRequest.KnownHeaders.UserAgentHeader,
USER_AGENT)
reply = self.covers.get(request)
def done() -> None:
@@ -1260,7 +1334,10 @@ class QtMusicApp(QMainWindow):
# -- воспроизведение --------------------------------------------------
def play_from_list(self, widget: QListWidget, item: QListWidgetItem) -> None:
def play_from_list(
self,
widget: QListWidget,
item: QListWidgetItem) -> None:
tracks = getattr(widget, "_tracks", [])
index = widget.row(item)
if not (0 <= index < len(tracks)):
@@ -1362,7 +1439,8 @@ class QtMusicApp(QMainWindow):
self.mpris.notify_seeked(value * 1000)
def on_slider_action(self, action: int) -> None:
# Колесо и стрелки, когда слайдер в фокусе (клик обрабатывает ClickSlider).
# Колесо и стрелки, когда слайдер в фокусе (клик обрабатывает
# ClickSlider).
if self.slider.maximum() > 0:
value = self.slider.value()
self.player.setPosition(value)
@@ -1374,7 +1452,8 @@ class QtMusicApp(QMainWindow):
if self.player.source().isEmpty():
return
duration = self.slider.maximum()
position = max(0, min(self.player.position() + delta_ms, max(0, duration - 500)))
position = max(0, min(self.player.position() +
delta_ms, max(0, duration - 500)))
self.player.setPosition(position)
self.slider.setValue(position)
self.elapsed_label.setText(fmt_millis(position))
@@ -1384,11 +1463,13 @@ class QtMusicApp(QMainWindow):
# -- MPRIS ------------------------------------------------------------
def mpris_play(self) -> None:
if self.player.playbackState() != QMediaPlayer.PlaybackState.PlayingState:
state = self.player.playbackState()
if state != QMediaPlayer.PlaybackState.PlayingState:
self.toggle_play()
def mpris_pause(self) -> None:
if self.player.playbackState() == QMediaPlayer.PlaybackState.PlayingState:
state = self.player.playbackState()
if state == QMediaPlayer.PlaybackState.PlayingState:
self.toggle_play()
def mpris_stop(self) -> None:
@@ -1401,9 +1482,8 @@ class QtMusicApp(QMainWindow):
if self.player.source().isEmpty():
return
duration = self.slider.maximum()
position = max(
0, min(self.player.position() + offset_us // 1000, max(0, duration - 500))
)
position = max(0, min(self.player.position() +
offset_us // 1000, max(0, duration - 500)))
self.player.setPosition(position)
self.slider.setValue(position)
self.elapsed_label.setText(fmt_millis(position))
@@ -1491,13 +1571,18 @@ class QtMusicApp(QMainWindow):
if item.get("type") == "track" and item.get("track")
]
self.run_task(fetch, lambda tracks: self.apply_more_wave(tracks, then_play), self.on_error)
self.run_task(
fetch, lambda tracks: self.apply_more_wave(
tracks, then_play), self.on_error)
def apply_more_wave(self, tracks: list[dict], then_play: int) -> None:
known = {str(track.get("id")) for track in self.wave}
added = [track for track in tracks if str(track.get("id")) not in known]
added = [
track for track in tracks if str(
track.get("id")) not in known]
self.wave.extend(added)
self.set_top_status(f"Волна · {len(self.wave)} · ♥ {len(self.liked_ids)}")
self.set_top_status(
f"Волна · {len(self.wave)} · ♥ {len(self.liked_ids)}")
if self.queue_name == "Моя волна":
self.queue = list(self.wave)
if then_play < len(self.queue) and added:
@@ -1536,7 +1621,12 @@ class QtMusicApp(QMainWindow):
)
return track_id
self.run_task(request, lambda _: self.apply_like(track, not liked), self.like_failed)
self.run_task(
request,
lambda _: self.apply_like(
track,
not liked),
self.like_failed)
def apply_like(self, track: dict, liked: bool) -> None:
track_id = str(track.get("id"))
@@ -1548,7 +1638,8 @@ class QtMusicApp(QMainWindow):
if self.current and str(self.current.get("id")) == track_id:
self.update_like_button(liked)
self.set_top_status(f"{self.queue_name} · ♥ {len(self.liked_ids)}")
self.toast("♥ Добавлено в избранное" if liked else "♡ Убрано из избранного")
self.toast(
"♥ Добавлено в избранное" if liked else "♡ Убрано из избранного")
if self.pages.currentWidget() is self.favorites_page:
self.load_favorites(force=True)
@@ -1664,14 +1755,20 @@ class QtMusicApp(QMainWindow):
if self._favorites_loading:
return
if self.favorites and not force:
self.fill_track_list(self.favorites_list, self.favorites, "Избранное")
self.fill_track_list(
self.favorites_list,
self.favorites,
"Избранное")
self.favorites_status.setText(f"{len(self.favorites)} трек(ов)")
return
self._favorites_loading = True
self.favorites_status.setText("Загружаю…")
if not self.favorites:
self.favorites_list.clear()
self.run_task(self._fetch_favorites, self.apply_favorites, self.favorites_failed)
self.run_task(
self._fetch_favorites,
self.apply_favorites,
self.favorites_failed)
def _fetch_favorites(self) -> list[dict]:
uid = self.uid or get_uid(self.api)
@@ -1705,10 +1802,8 @@ class QtMusicApp(QMainWindow):
**{"page-size": 25},
nocorrect="true",
)
return (
((payload.get("result") or {}).get("tracks") or {}).get("results")
or []
)
return (((payload.get("result") or {}).get(
"tracks") or {}).get("results") or [])
self.run_task(search, self.apply_search, self.search_failed)