Files
subpy/textual-test.py
T
2025-01-29 17:02:38 -06:00

215 lines
6.8 KiB
Python

import logging
import os
from enum import Enum
LOG_FILE = 'textual.log'
LOGGING_LEVEL = logging.DEBUG
LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
# Clear Log File
os.remove(LOG_FILE)
logging.basicConfig(filename=LOG_FILE, level=LOGGING_LEVEL, format=LOG_FORMAT)
import SubSonic
from textual import on, events
from textual.app import App, ComposeResult
from textual.widgets import Footer, Header, OptionList, DataTable, Tabs, Tab, TabbedContent, TabPane
from textual.widgets.option_list import Option
u = 'pseudo'
p = 'telegram9dock-MICHEL'
class Menus(Enum):
MAIN = "MAIN"
ARTISTS = "Artists"
ARTISTSONGS = "ArtistSongs"
ARTISTALBUMS = "ArtistAlbums"
ALBUMS = "Albums"
ALBUMSONGS = "AlbumSongs"
class TextualSubpyPlayer(App):
# BINDINGS = [
# ('backspace', 'menu_back()', 'Go back a menu')
# ]
artists: list[SubSonic.Artist]
selectedArtist: SubSonic.Artist
albums: list[SubSonic.Album]
conn: SubSonic.SubpyConn
currentMenu: Menus
lastMenu: Menus
last_menu_type: any
def compose(self) -> ComposeResult:
self.currentMenu = Menus.MAIN
self.lastMenu = Menus.MAIN
self.last_menu_type = None
with TabbedContent(initial="Artists"):
with TabPane("Artists", id="Artists"):
yield OptionList(id="Artists")
with TabPane("Albums", id="Albums"):
yield DataTable(id="Albums")
yield Footer()
# async def action_menu_back(self) -> None:
# logging.debug('Menu Back Called')
# match self.lastMenu:
# case Menus.MAIN:
# logging.debug("Moving back to the main menu")
# await self.main_menu()
# case Menus.ARTISTALBUMS:
# logging.debug("Moving back to Artist Albums")
# await self.selectArtistAlbumView(self.selectedArtist.id)
# case Menus.ARTISTS:
# logging.debug("Moving backt to artists")
# await self.selectArtistsView()
# case _:
# logging.debug(f"Last Menu unknown, {self.lastMenu}")
def on_key(self, event: events.Key) -> None:
logging.debug(f'Key Pressed {event.name}')
# def on_tabs_tab_activated(self, event: Tabs.TabActivated) -> None:
# logging.debug(f'{event.tab.id} selected')
@on(TabbedContent.TabActivated)
async def artists_tab(self, event: TabbedContent.TabActivated) -> None:
if self.last_menu_type:
await self.query_one(self.last_menu_type).remove()
self.last_menu_type = None
logging.debug(f'{event.pane.id} tab selected')
id = event.pane.id
# id = event.tab.id
match id:
case "Artists":
self.artists = self.conn.getArtists()
artistList: OptionList = self.query_one(OptionList)
if not artistList:
artistList: OptionList = await self._getArtistMenu()
await self.mount(artistList)
for artist in self.artists:
artistList.add_option(Option(artist.name, artist.id))
self.last_menu_type = OptionList
def action_toggle_dark(self) -> None:
"""An action to toggle dark mode."""
self.theme = (
"textual-dark" if self.theme == "textual-light" else "textual-light"
)
async def _getArtistMenu(self) -> OptionList:
# self.artists = self.conn.getArtists()
return OptionList(id=Menus.ARTISTS.value)
# @on(OptionList.OptionSelected, f'#{Menus.MAIN.value}')
# async def selectMainMenu(self, event: OptionList.OptionSelected) -> None:
# match event.option_id:
# case "BrowseArtists":
# logging.debug('View Artists Selected')
# await self.selectArtistsView()
# @on(OptionList.OptionSelected, f"#{Menus.ARTISTS.value}")
# async def artistSelected(self, event: OptionList.OptionSelected) -> None:
# logging.debug(f'Artist {event.option.prompt} Selected')
# self.lastMenu = Menus.ARTISTS
# for artist in self.artists:
# if event.option_id == artist.id:
# self.selectedArtist = artist
# await self.selectArtistAlbumView(self.selectedArtist.id)
# @on(DataTable.RowSelected, "#ArtistAlbums")
# async def ArtistAlbumSelected(self, event: DataTable.RowSelected) -> None:
# self.lastMenu = Menus.ARTISTALBUMS
# row_key = event.row_key
# row = event.data_table.get_row(row_key)
# logging.debug(f'Album {row[0]} Selected')
# await self.selectAlbumSongsView(row_key.value)
async def selectAlbumSongsView(self, album_id: str) -> None:
logging.debug("Setting up album songs DataTable")
self.currentMenu = Menus.ALBUMSONGS
songs = conn.getAlbumSongs(album_id)
albumSongs = DataTable(id="AlbumSongs")
await self.mount(albumSongs)
albumSongs.cursor_type = 'row'
albumSongs.add_columns("#", "Title", "Artist", "Duration", "Bitrate")
for song in songs:
albumSongs.add_row(song.trackNumber, song.title, song.artist, song.duration, song.bitRate, key=song.id)
self.query_one(f"#{self.lastMenu.value}").remove()
async def selectArtistAlbumView(self, artist_id: str) -> None:
logging.debug("Setting up album DataTable")
self.currentMenu = Menus.ARTISTALBUMS
albumTable = DataTable(id="ArtistAlbums")
await self.mount(albumTable)
albumTable.cursor_type = 'row'
albumTable.add_columns("Title", "Songs")
self.albums = conn.getArtistAlbums(artist_id)
for album in self.albums:
albumTable.add_row(album.title, album.songCount, key=album.id)
self.query_one(f"#{self.lastMenu.value}").remove()
async def main_menu(self) -> None:
await self.mount(OptionList(
Option("Browse Artists", id="BrowseArtists"),
Option("Browse Albums"),
Option("Browse Songs"),
Option("Browse Playlists"),
id=Menus.MAIN.value
))
self.query_one(f"#{self.currentMenu.value}").remove()
async def selectArtistsView(self) -> None:
artistList: OptionList = await self._getArtistMenu()
self.currentMenu = Menus.ARTISTS
await self.mount(artistList)
for artist in self.artists:
artistList.add_option(Option(artist.name, artist.id))
self.query_one(f"#{self.lastMenu.value}").remove()
if __name__ == '__main__':
app = TextualSubpyPlayer()
app.conn = SubSonic.SubpyConn(u, p, "https://music.0x01fe.net")
app.run()