stole the settings menu from my Berry IDE lol

This commit is contained in:
2026-01-18 07:04:54 +11:00
parent 8e69b0d602
commit 23a99fddf5
3 changed files with 166 additions and 2 deletions

59
src/settings_store.py Normal file
View File

@@ -0,0 +1,59 @@
from textual.app import App
from pathlib import Path
import os
import configparser
from typing import Any
class ConfigHandler:
def __init__(self, app: App):
self.app: App = app
self.config: configparser.ConfigParser = configparser.ConfigParser()
self.plugin_defined_settings = {}
self.config_dir: str = self.ensure_hidden_config_dir()
self.load_settings()
def ensure_hidden_config_dir(self):
config_dir = Path.home() / ".termdaw"
config_dir.mkdir(parents=True, exist_ok=True)
return config_dir
def get(self, section: str, option: str):
if not self.config.has_section(section):
self.config.add_section(section)
if not self.config.has_option(section, option):
self.set(section, option, "0")
return "0"
return self.config.get(section, option, fallback=None)
def set(self, section: str, option: str, new_value: str):
if not self.config.has_section(section):
self.config.add_section(section)
self.config.set(section, option, new_value)
self.write_settings()
def apply_settings(self):
self.app.theme = self.get("appearance", "colour_theme")
def write_settings(self):
with open(self.config_dir / "config.ini", "w") as configfile:
self.config.write(configfile)
def load_settings(self):
if os.path.isfile(self.config_dir / "config.ini"):
self.config.read(self.config_dir / "config.ini")
return
self.config["config"] = {
"version": "1"
}
self.config["appearance"] = {
"colour_theme": "textual-dark"
}
with open(self.config_dir / "config.ini", "w") as configfile:
self.config.write(configfile)

View File

@@ -9,9 +9,12 @@ from ui.widgets.timeline import Timeline, TimelineRow
from ui.widgets.project_settings import ProjectSettings
from ui.widgets.channel import Channel
from ui.widgets.context_menu import ContextMenu, NoSelectStatic
from ui.widgets.chunk_types.audio import AudioChunk, Chunk
from ui.screens.settings import SettingsScreen
from project import ProjectChannel, Project, ChunkType
from ui.widgets.chunk_types.audio import AudioChunk, Chunk
from settings_store import ConfigHandler
class AppUI(App):
@@ -23,6 +26,8 @@ class AppUI(App):
self.last_zoom_level = self.zoom_level
self.project = project
self.config_handler = ConfigHandler(self)
self.open_project_path = None
self.first_tab_click = True # stupid events firing when the app is first composed :/
@@ -135,6 +140,9 @@ class AppUI(App):
)
), callback=callback)
case "Settings":
self.push_screen(SettingsScreen())
case _:
self.notify("Sorry, that isn't implemented yet... ;-;", severity="warning")
@@ -175,4 +183,8 @@ class AppUI(App):
yield Sidebar()
yield Timeline()
yield ProjectSettings()
yield Footer()
yield Footer()
def on_mount(self):
# load config into the UI
self.config_handler.apply_settings()

View File

@@ -0,0 +1,93 @@
from textual.screen import ModalScreen
from textual.widgets import Label, Select, TabbedContent, TabPane, Switch, Input, Rule, Static
from textual.containers import Vertical, HorizontalGroup, VerticalGroup, VerticalScroll
from textual.binding import Binding
class SettingsScreen(ModalScreen):
border_title = "Settings"
DEFAULT_CSS = """
SettingsScreen {
align: center middle;
#window {
border: panel $primary;
background: $background;
width: 65%;
height: 65%;
padding: 1;
}
TabPane {
padding: 1;
}
Rule {
color: $boost;
}
.thingy {
margin-top: 2;
text-style: bold;
}
.setting {
padding: 0 2;
content-align: center middle;
margin-bottom: 1;
.setting-name {
text-style: bold;
}
.setting-desc {
text-style: dim;
width: 100%;
min-width: 30;
}
VerticalGroup {
width: 50%;
min-width: 20;
margin-right: 1;
}
Select, Input {
max-width: 30;
}
}
}
"""
BINDINGS = [
Binding("escape", "close", "Close")
]
def __init__(self):
super().__init__()
def action_close(self):
self.dismiss()
def on_select_changed(self, event: Select.Changed):
if event.select.id == "colour-theme":
self.app.theme = event.value
self.app.config_handler.set("appearance", "colour_theme", str(event.value))
def compose(self):
with Vertical(id="window") as window:
window.border_title = "Settings"
with TabbedContent():
with TabPane("Appearance"):
with VerticalScroll():
with HorizontalGroup(classes="setting"):
with VerticalGroup():
yield Label("Colour Theme", classes="setting-name")
yield Label("Colour theme used for the entire Berry app. You can get more themes with plugins!", classes="setting-desc")
yield Select.from_values(
(theme_name for theme_name in self.app._registered_themes.keys() if theme_name != "textual-ansi"),
allow_blank=False,
id="colour-theme",
value=self.app.theme
)