Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ coverage.xml
tmp/
pytest-tmp/
cover/
.npm-cache/

# Translations
*.mo
*.pot
!locale/
!locale/**/
!locale/**/*.mo

# Django stuff:
*.log
Expand Down
242 changes: 138 additions & 104 deletions GUI/app.py

Large diffs are not rendered by default.

272 changes: 212 additions & 60 deletions GUI/widgets/MBListView.py

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion GUI/widgets/browserChrome.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from PyQt6.QtGui import QFont
from PyQt6.QtWidgets import QFrame, QHBoxLayout, QLabel, QSplitter, QVBoxLayout, QWidget

from infrastructure.i18n import tr as _

from ..styles import FONT_FAMILY, Colors, Metrics, btn_css


Expand Down Expand Up @@ -73,7 +75,7 @@ def __init__(
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)

self.title_label = QLabel(title, self)
self.title_label = QLabel(_(title), self)
self.title_label.setFont(QFont(FONT_FAMILY, Metrics.FONT_TITLE, QFont.Weight.Bold))
self.title_label.setStyleSheet(f"""
color:{Colors.TEXT_PRIMARY};
Expand Down
16 changes: 11 additions & 5 deletions GUI/widgets/gridHeaderBar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import QFrame, QHBoxLayout, QLineEdit, QMenu, QPushButton, QSizePolicy

from infrastructure.i18n import tr as _

from ..styles import Colors, Metrics, btn_css, input_css

# Sort definitions per category: (display_label, sort_key, reverse)
Expand Down Expand Up @@ -63,7 +65,7 @@ def __init__(self, parent=None):
layout.setContentsMargins(8, 0, 8, 0)
layout.setSpacing(6)

self._sort_btn = QPushButton(f"Sort: {_DEFAULT_LABEL} \u25be")
self._sort_btn = QPushButton(self._sort_button_text(_DEFAULT_LABEL))
self._sort_btn.setStyleSheet(
btn_css(padding="4px 10px", radius=Metrics.BORDER_RADIUS_SM)
)
Expand All @@ -72,7 +74,7 @@ def __init__(self, parent=None):
self._sort_btn.clicked.connect(self._show_sort_menu)

self._search = QLineEdit()
self._search.setPlaceholderText("Search\u2026")
self._search.setPlaceholderText(_("Search\u2026"))
self._search.setFixedWidth(200)
self._search.setStyleSheet(
input_css(radius=Metrics.BORDER_RADIUS_SM, padding="4px 10px")
Expand All @@ -96,7 +98,7 @@ def resetState(self) -> None:
self._search.clear()
self._search.blockSignals(False)
self._active_label = _DEFAULT_LABEL
self._sort_btn.setText(f"Sort: {_DEFAULT_LABEL} \u25be")
self._sort_btn.setText(self._sort_button_text(_DEFAULT_LABEL))
# Emit the default sort so grid is reset even if called from other paths
self.sort_changed.emit("title", False)

Expand Down Expand Up @@ -130,7 +132,7 @@ def _show_sort_menu(self) -> None:

all_sorts = _SORTS.get(self._category, _SORTS["Albums"])
for label, key, reverse in all_sorts:
action = cast(QAction, menu.addAction(label))
action = cast(QAction, menu.addAction(_(label)))
action.setCheckable(True)
action.setChecked(label == self._active_label)
action.triggered.connect(
Expand All @@ -143,5 +145,9 @@ def _show_sort_menu(self) -> None:

def _on_sort_selected(self, label: str, key: str, reverse: bool) -> None:
self._active_label = label
self._sort_btn.setText(f"Sort: {label} \u25be")
self._sort_btn.setText(self._sort_button_text(label))
self.sort_changed.emit(key, reverse)

@staticmethod
def _sort_button_text(label: str) -> str:
return _("Sort: {label} \u25be").format(label=_(label))
33 changes: 22 additions & 11 deletions GUI/widgets/musicBrowser.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
QVBoxLayout,
)

from infrastructure.i18n import tr as _
from iTunesDB_Shared.constants import (
MEDIA_TYPE_AUDIO,
MEDIA_TYPE_AUDIOBOOK,
Expand Down Expand Up @@ -43,6 +44,12 @@

log = logging.getLogger(__name__)

_SELECTION_TITLE_BY_CATEGORY = {
"Albums": "Select an Album",
"Artists": "Select an Artist",
"Genres": "Select a Genre",
}

if TYPE_CHECKING:
from app_core.services import (
DeviceSessionService,
Expand Down Expand Up @@ -122,6 +129,7 @@ def __init__(

# Bottom: Track Browser
self.trackContainer = QFrame()
self.trackContainer.setMinimumSize(0, 0)
self.trackContainerLayout = QVBoxLayout(self.trackContainer)
self.trackContainerLayout.setContentsMargins(0, 0, 0, 0)
self.trackContainerLayout.setSpacing(0)
Expand Down Expand Up @@ -326,7 +334,7 @@ def _refreshCurrentCategory(self):
self.browserTrack.clearTable() # Clear track list before reloading
self.browserTrack.clearFilter()
self.browserTrack.loadTracks(media_type_filter=MEDIA_TYPE_AUDIO)
self.trackListTitleBar.setTitle("All Tracks")
self.trackListTitleBar.setTitle("All Tracks", translate=True)
self.trackListTitleBar.resetColor()
self.trackListTitleBar.setFullscreenMode(True)
elif category == "Playlists":
Expand Down Expand Up @@ -360,7 +368,7 @@ def _refreshCurrentCategory(self):
self.browserTrack.clearTable()
self.browserTrack.clearFilter()
self.browserTrack.loadTracks(media_type_filter=MEDIA_TYPE_AUDIOBOOK)
self.trackListTitleBar.setTitle(category)
self.trackListTitleBar.setTitle(category, translate=True)
self.trackListTitleBar.resetColor()
self.trackListTitleBar.setFullscreenMode(True)
elif category in ("Videos", "Movies", "TV Shows", "Music Videos"):
Expand All @@ -377,7 +385,7 @@ def _refreshCurrentCategory(self):
self.browserTrack.clearTable()
self.browserTrack.clearFilter()
self.browserTrack.loadTracks(media_type_filter=_MEDIA_TYPE_FILTER[category])
self.trackListTitleBar.setTitle(category)
self.trackListTitleBar.setTitle(category, translate=True)
self.trackListTitleBar.resetColor()
self.trackListTitleBar.setFullscreenMode(True)
else:
Expand All @@ -393,7 +401,10 @@ def _refreshCurrentCategory(self):
# won't include video tracks in results.
self.browserTrack.loadTracks(media_type_filter=MEDIA_TYPE_AUDIO)
self.browserTrack.clearFilter()
self.trackListTitleBar.setTitle(f"Select a{'n' if category[0] in 'AE' else ''} {category[:-1]}")
self.trackListTitleBar.setTitle(
_SELECTION_TITLE_BY_CATEGORY.get(category, f"Select {category}"),
translate=True,
)
self.trackListTitleBar.resetColor()
self.trackListTitleBar.setFullscreenMode(False)

Expand Down Expand Up @@ -451,15 +462,15 @@ def _onGridItemContextRequested(self, items: object, global_pos) -> None:

edit_action = None
if len(album_items) == 1:
edit_action = menu.addAction("Edit")
edit_action = menu.addAction(_("Edit"))
if edit_action is not None:
edit_icon = glyph_icon("edit", 14, Colors.TEXT_PRIMARY)
if edit_icon is not None:
edit_action.setIcon(edit_icon)
if int(album_items[0].get("track_count", 0) or 0) < 1:
edit_action.setEnabled(False)

conversion_action = menu.addAction("Convert to a single chaptered track")
conversion_action = menu.addAction(_("Convert to a single chaptered track"))
if conversion_action is None:
return

Expand All @@ -476,7 +487,7 @@ def _onGridItemContextRequested(self, items: object, global_pos) -> None:
unify_context = self._album_artwork_unify_context(album_items[0])
if unify_context is not None:
menu.addSeparator()
unify_action = menu.addAction("Unify Artwork")
unify_action = menu.addAction(_("Unify Artwork"))
if unify_action is not None:
unify_icon = glyph_icon("photo", 14, Colors.TEXT_PRIMARY)
if unify_icon is not None:
Expand Down Expand Up @@ -547,8 +558,8 @@ def _show_unify_artwork_dialog(
except Exception as exc:
QMessageBox.warning(
self,
"Unify Artwork",
f"Could not prepare artwork:\n\n{exc}",
_("Unify Artwork"),
_("Could not prepare artwork:\n\n{error}").format(error=exc),
)
return

Expand All @@ -569,8 +580,8 @@ def _show_unify_artwork_dialog(
pass
QMessageBox.warning(
self,
"Unify Artwork",
f"Could not stage artwork update:\n\n{exc}",
_("Unify Artwork"),
_("Could not stage artwork update:\n\n{error}").format(error=exc),
)

def refresh_artwork_appearance(self) -> None:
Expand Down
Loading