122 lines
4.7 KiB
Python
122 lines
4.7 KiB
Python
import os
|
|
from pathlib import Path
|
|
import memoria
|
|
from textual.app import App, ComposeResult
|
|
from textual.widgets import Header, Footer, ListView, ListItem, Label, Static, Button
|
|
from textual.containers import Container
|
|
from textual.screen import Screen
|
|
|
|
ver = 0.01
|
|
|
|
# --- MemApp 学习屏幕 ---
|
|
class MemAppLearningScreen(Screen):
|
|
BINDINGS = [
|
|
("q", "go_back", "返回"),
|
|
("escape", "quit_app", "退出")
|
|
]
|
|
|
|
def __init__(self, file_to_learn: str, history_file: str, name: str | None = None, id: str | None = None, classes: str | None = None) -> None:
|
|
super().__init__(name=name, id=id, classes=classes)
|
|
self.file_to_learn = file_to_learn
|
|
self.history_file = history_file
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield Header()
|
|
with Container(id="learning_screen_container"):
|
|
yield Label(f"正在学习文件: [b]{Path(self.file_to_learn).name}[/b]", classes="learning-info")
|
|
yield Label(f"历史文件: [b]{Path(self.history_file).name}[/b]", classes="learning-info")
|
|
yield Label("\n[i]点击 '开始记忆' 进入学习模式.[/i]", classes="placeholder-message")
|
|
yield Static("\n按 [b]Q[/b] 返回;按 [b]ESC[/b] 退出.", classes="instructions")
|
|
yield Button("开始记忆", id="start_memorizing_button", variant="primary", classes="start-button")
|
|
yield Static(f"\n以下是全文:\n", classes="read-info")
|
|
with open(self.file_to_learn, 'r', encoding='UTF-8') as f:
|
|
for i in f.readlines():
|
|
yield Static(' ' + i, classes="read-info")
|
|
yield Footer()
|
|
|
|
def action_go_back(self):
|
|
self.app.pop_screen()
|
|
|
|
def action_quit_app(self):
|
|
self.app.exit()
|
|
|
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
if event.button.id == "start_memorizing_button":
|
|
self.app.push_screen(
|
|
memoria.MemScreen(
|
|
file_to_learn=self.file_to_learn,
|
|
history_file=self.history_file
|
|
)
|
|
)
|
|
|
|
# --- 文件选择屏幕 ---
|
|
class FileSelectionScreen(Screen):
|
|
global ver
|
|
def compose(self) -> ComposeResult:
|
|
yield Header()
|
|
yield Container(
|
|
Label(f'欢迎使用 "青鸟" 辅助记忆软件, 版本 {ver}', classes="title-label"),
|
|
Label("选择要学习的文件:", classes="title-label"),
|
|
ListView(id="file-list", classes="file-list-view")
|
|
)
|
|
yield Footer()
|
|
|
|
def on_mount(self) -> None:
|
|
Path("./history").mkdir(parents=True, exist_ok=True)
|
|
Path("./library").mkdir(parents=True, exist_ok=True)
|
|
|
|
file_list_widget = self.query_one("#file-list", ListView)
|
|
library_path = Path("./library")
|
|
txt_files = sorted([f.name for f in library_path.iterdir() if f.suffix == ".txt"])
|
|
|
|
if txt_files:
|
|
for filename in txt_files:
|
|
file_list_widget.append(ListItem(Label(filename)))
|
|
else:
|
|
file_list_widget.append(ListItem(Static("在 ./library/ 中未找到任何 .txt 文件。请放置文件后重启应用。")))
|
|
file_list_widget.disabled = True
|
|
|
|
def on_list_view_selected(self, event: ListView.Selected) -> None:
|
|
if not isinstance(event.item, ListItem):
|
|
self.notify("无法选择此项。", severity="error")
|
|
return
|
|
|
|
selected_label = event.item.query_one(Label)
|
|
if "未找到任何 .txt 文件" in str(selected_label.renderable):
|
|
self.notify("请先在 `./library/` 目录中放置 .txt 文件。", severity="warning")
|
|
return
|
|
|
|
selected_filename = str(selected_label.renderable)
|
|
file_to_learn_path = Path("./library") / selected_filename
|
|
|
|
history_file_name = f"{Path(selected_filename).stem}_history.json"
|
|
history_file_path = Path("./history") / history_file_name
|
|
|
|
self.notify(f"已选择: {selected_filename}", timeout=2)
|
|
|
|
self.app.push_screen(MemAppLearningScreen(
|
|
file_to_learn=str(file_to_learn_path),
|
|
history_file=str(history_file_path)
|
|
))
|
|
|
|
def action_quit_app(self) -> None:
|
|
self.app.exit()
|
|
|
|
# --- 主 Textual 应用类 ---
|
|
class MemAppLauncher(App):
|
|
CSS_PATH = "styles.css"
|
|
TITLE = '青鸟 辅助记忆程序'
|
|
BINDINGS = [("escape", "quit", "退出"), ("d", "toggle_dark", "改变色调")]
|
|
SCREENS = {
|
|
"file_selection_screen": FileSelectionScreen,
|
|
}
|
|
|
|
def on_mount(self) -> None:
|
|
self.action_toggle_dark()
|
|
self.push_screen("file_selection_screen")
|
|
|
|
if __name__ == "__main__":
|
|
css_path = Path("styles_dashboard.css")
|
|
app = MemAppLauncher()
|
|
app.run()
|