规范代码
This commit is contained in:
169
main.py
169
main.py
@@ -1,35 +1,43 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.widgets import Header, Footer, ListView, ProgressBar, DirectoryTree, ListItem, Label, Static, Button
|
||||
from textual.widgets import (
|
||||
Header,
|
||||
Footer,
|
||||
ListView,
|
||||
ProgressBar,
|
||||
DirectoryTree,
|
||||
ListItem,
|
||||
Label,
|
||||
Static,
|
||||
Button,
|
||||
)
|
||||
from textual.containers import Container, Horizontal, Center
|
||||
from textual.screen import Screen
|
||||
import pathlib
|
||||
import threading
|
||||
import edge_tts as tts
|
||||
from playsound import playsound
|
||||
|
||||
import particles as pt
|
||||
from reactor import Reactor, Apparatus
|
||||
import auxiliary as aux
|
||||
import compositions as compo
|
||||
|
||||
import builtins
|
||||
|
||||
# 保存原始的 open 函数
|
||||
_original_open = builtins.open
|
||||
|
||||
# 定义新的 open 函数,默认使用 UTF-8
|
||||
|
||||
def _open(*args, **kwargs):
|
||||
if 'encoding' not in kwargs:
|
||||
kwargs['encoding'] = 'utf-8'
|
||||
if "encoding" not in kwargs:
|
||||
kwargs["encoding"] = "utf-8"
|
||||
return _original_open(*args, **kwargs)
|
||||
|
||||
# 替换全局的 open
|
||||
|
||||
builtins.open = _open
|
||||
|
||||
ver = '0.3.0b'
|
||||
ver = "0.3.0b"
|
||||
|
||||
config = aux.ConfigFile("config.toml")
|
||||
|
||||
|
||||
class MemScreen(Screen):
|
||||
BINDINGS = [
|
||||
("d", "toggle_dark", "改变色调"),
|
||||
@@ -49,38 +57,30 @@ class MemScreen(Screen):
|
||||
("/", "press('q0')", None),
|
||||
]
|
||||
btn = dict()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
nucleon_file: pt.NucleonUnion,
|
||||
electron_file: pt.ElectronUnion,
|
||||
tasked_num
|
||||
tasked_num,
|
||||
):
|
||||
super().__init__(name=None, id=None, classes=None)
|
||||
self.reactor = Reactor(nucleon_file, electron_file, self, tasked_num)
|
||||
self.stage = 1
|
||||
self.stage += self.reactor.set_round_templated(self.stage)
|
||||
##print(self.reactor.procession)
|
||||
self.reactor.forward()
|
||||
#self.compo:compo.Composition = compo.Placeholder(self)
|
||||
self.compo = next(self.reactor.current_appar)
|
||||
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
#print(self.compo)
|
||||
yield Header(show_clock=True)
|
||||
with Center():
|
||||
yield Static(f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}")
|
||||
#yield ProgressBar(total=len(self.reactor.procession) - 1, show_percentage=False, show_eta=False, id="progress")
|
||||
yield Static(
|
||||
f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}"
|
||||
)
|
||||
yield from self.compo.compose()
|
||||
yield Footer()
|
||||
|
||||
"""
|
||||
def _get_progress_text(self):
|
||||
return f"{len(self.reactor.procession) - self.reactor.index}/{len(self.reactor.procession)}"
|
||||
"""
|
||||
|
||||
def on_mount(self):
|
||||
# 首次挂载时调用
|
||||
pass
|
||||
|
||||
def on_button_pressed(self, event):
|
||||
@@ -90,13 +90,12 @@ class MemScreen(Screen):
|
||||
def _forward_judge(self, ret):
|
||||
if ret == -1:
|
||||
return
|
||||
if ret == 0: # 成功
|
||||
if ret == 0:
|
||||
try:
|
||||
self.compo = next(self.reactor.current_appar)
|
||||
self.refresh_ui()
|
||||
except StopIteration:
|
||||
nxt = self.reactor.forward(1)
|
||||
#print(2)
|
||||
try:
|
||||
self.compo = next(self.reactor.current_appar)
|
||||
except:
|
||||
@@ -106,13 +105,13 @@ class MemScreen(Screen):
|
||||
if self.stage == 4:
|
||||
if config.get("save"):
|
||||
self.reactor.save()
|
||||
self.compo = compo.Finished(self, None, pt.Atom.placeholder())
|
||||
self.compo = compo.Finished(
|
||||
self, None, pt.Atom.placeholder()
|
||||
)
|
||||
self.refresh_ui()
|
||||
#self._show_finished_screen("今日目标已完成")
|
||||
else:
|
||||
self.reactor.set_round_templated(self.stage)
|
||||
self.reactor.forward(1)
|
||||
#self._update_ui()
|
||||
self.stage += 1
|
||||
self.compo = next(self.reactor.current_appar)
|
||||
self.refresh_ui()
|
||||
@@ -121,71 +120,47 @@ class MemScreen(Screen):
|
||||
else:
|
||||
self.refresh_ui()
|
||||
return
|
||||
if ret == 1: # 不允许前进
|
||||
if ret == 1:
|
||||
self.refresh_ui()
|
||||
return
|
||||
|
||||
def refresh_ui(self):
|
||||
self.call_later(self.recompose)
|
||||
#self.call_later(lambda: self.query_one("#progress", expect_type=ProgressBar).advance(self.reactor.index))
|
||||
##print(area.children)
|
||||
#for child in list(area.children):
|
||||
# child.remove() # 致敬传奇组件树 DOM
|
||||
##print(1,list(self.compo.compose()))
|
||||
#area.mount(*list(self.compo.compose()))
|
||||
|
||||
def report(self, quality):
|
||||
assessment = self.reactor.report(self.reactor.current_atom, quality)
|
||||
return assessment
|
||||
"""if assessment == 1:
|
||||
# 需要复习
|
||||
feedback_label.update(f"评分为 {quality}, 已经加入至复习, 请重复记忆")
|
||||
else:
|
||||
ret = self.reactor.forward(1)
|
||||
if ret == -1:
|
||||
if self.reactor.round_set == 0:
|
||||
if self.stage == 4:
|
||||
# NOTE #
|
||||
if config.get("save"):
|
||||
self.reactor.save()
|
||||
self._show_finished_screen("今日目标已完成")
|
||||
else:
|
||||
self.reactor.set_round_templated(self.stage)
|
||||
self.reactor.forward(1)
|
||||
self._update_ui()
|
||||
self.stage += 1
|
||||
return
|
||||
#feedback_label.update("") # 清除反馈消息
|
||||
self._update_ui()"""
|
||||
|
||||
#def action_press(self, btnid):
|
||||
# self.on_button_pressed(btnid)
|
||||
|
||||
def action_play_voice(self):
|
||||
def play():
|
||||
cache_dir = pathlib.Path(f"./cache/voice/")
|
||||
cache_dir.mkdir(parents = True, exist_ok = True)
|
||||
cache = cache_dir / f"{self.reactor.current_atom[1].content.replace("/","")}.wav"
|
||||
cache_dir.mkdir(parents=True, exist_ok=True)
|
||||
cache = cache_dir / f"{self.reactor.current_atom[1].content.replace('/','')}.wav"
|
||||
if not cache.exists():
|
||||
communicate = tts.Communicate(self.reactor.current_atom[1].content.replace("/",""), "zh-CN-YunjianNeural")
|
||||
communicate.save_sync(f"./cache/voice/{self.reactor.current_atom[1].content.replace("/","")}.wav")
|
||||
communicate = tts.Communicate(
|
||||
self.reactor.current_atom[1].content.replace("/", ""),
|
||||
"zh-CN-YunjianNeural",
|
||||
)
|
||||
communicate.save_sync(
|
||||
f"./cache/voice/{self.reactor.current_atom[1].content.replace('/','')}.wav"
|
||||
)
|
||||
playsound(str(cache))
|
||||
|
||||
threading.Thread(target=play).start()
|
||||
|
||||
def action_toggle_dark(self):
|
||||
self.app.action_toggle_dark()
|
||||
|
||||
def action_pop_screen(self):
|
||||
"""返回到上一个屏幕"""
|
||||
self.app.pop_screen()
|
||||
|
||||
class PreparationScreen(Screen):
|
||||
BINDINGS = [
|
||||
("q", "go_back", "返回"),
|
||||
("escape", "quit_app", "退出")
|
||||
]
|
||||
|
||||
def __init__(self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion) -> None:
|
||||
class PreparationScreen(Screen):
|
||||
BINDINGS = [("q", "go_back", "返回"), ("escape", "quit_app", "退出")]
|
||||
|
||||
def __init__(
|
||||
self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion
|
||||
) -> None:
|
||||
super().__init__(name=None, id=None, classes=None)
|
||||
self.nucleon_file = nucleon_file
|
||||
self.electron_file = electron_file
|
||||
@@ -194,10 +169,19 @@ class PreparationScreen(Screen):
|
||||
yield Header(show_clock=True)
|
||||
with Container(id="learning_screen_container"):
|
||||
yield Label(f"记忆项目: [b]{self.nucleon_file.name}[/b]\n")
|
||||
yield Label(f"核子文件对象: ./nucleon/[b]{self.nucleon_file.name}[/b].toml")
|
||||
yield Label(f"电子文件对象: ./electron/[b]{self.electron_file.name}[/b].toml")
|
||||
yield Label(
|
||||
f"核子文件对象: ./nucleon/[b]{self.nucleon_file.name}[/b].toml"
|
||||
)
|
||||
yield Label(
|
||||
f"电子文件对象: ./electron/[b]{self.electron_file.name}[/b].toml"
|
||||
)
|
||||
yield Label(f"核子数量:{len(self.nucleon_file)}")
|
||||
yield Button("开始记忆", id="start_memorizing_button", variant="primary", classes="start-button")
|
||||
yield Button(
|
||||
"开始记忆",
|
||||
id="start_memorizing_button",
|
||||
variant="primary",
|
||||
classes="start-button",
|
||||
)
|
||||
yield Static(f"\n全文如下:\n")
|
||||
yield Static(self._get_full_content(), classes="full")
|
||||
yield Footer()
|
||||
@@ -205,7 +189,7 @@ class PreparationScreen(Screen):
|
||||
def _get_full_content(self):
|
||||
content = ""
|
||||
for i in self.nucleon_file.nucleons:
|
||||
content += i['content']
|
||||
content += i["content"]
|
||||
return content
|
||||
|
||||
def action_go_back(self):
|
||||
@@ -215,76 +199,79 @@ class PreparationScreen(Screen):
|
||||
self.app.exit()
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
pass
|
||||
if event.button.id == "start_memorizing_button":
|
||||
#init_file(Path(self.atom_file).name)
|
||||
newscr = MemScreen(self.nucleon_file, self.electron_file, config.get("tasked_number", 8))
|
||||
self.app.push_screen(
|
||||
newscr
|
||||
newscr = MemScreen(
|
||||
self.nucleon_file, self.electron_file, config.get("tasked_number", 8)
|
||||
)
|
||||
#if event.button.id == "edit_metadata_button":
|
||||
# init_file(Path(self.atom_file).name)
|
||||
# os.system("reset;nano ./data/" + str(Path(self.atom_file).name.replace(".txt", "_atoms.json")))
|
||||
self.app.push_screen(newscr)
|
||||
|
||||
|
||||
class FileSelectorScreen(Screen):
|
||||
global ver
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(show_clock=True)
|
||||
yield Container(
|
||||
Label(f'欢迎使用 "潜进" 辅助记忆软件, 版本 {ver}', classes="title-label"),
|
||||
Label("选择要学习的文件:", classes="title-label"),
|
||||
ListView(id="file-list", classes="file-list-view")
|
||||
ListView(id="file-list", classes="file-list-view"),
|
||||
)
|
||||
yield Footer()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
file_list_widget = self.query_one("#file-list", ListView)
|
||||
nucleon_path = pathlib.Path("./nucleon")
|
||||
nucleon_files = sorted([f.name for f in nucleon_path.iterdir() if f.suffix == ".toml"])
|
||||
nucleon_files = sorted(
|
||||
[f.name for f in nucleon_path.iterdir() if f.suffix == ".toml"]
|
||||
)
|
||||
|
||||
if nucleon_files:
|
||||
for filename in nucleon_files:
|
||||
file_list_widget.append(ListItem(Label(filename)))
|
||||
else:
|
||||
file_list_widget.append(ListItem(Static("在 ./nucleon/ 中未找到任何核子文件. 请放置文件后重启应用.")))
|
||||
file_list_widget.append(
|
||||
ListItem(Static("在 ./nucleon/ 中未找到任何核子文件. 请放置文件后重启应用."))
|
||||
)
|
||||
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 "未找到任何 .toml 文件" in str(selected_label.renderable):
|
||||
self.notify("请先在 `./atoms/` 目录中放置 .toml 文件。", severity="warning")
|
||||
return
|
||||
|
||||
selected_filename = str(selected_label.renderable)
|
||||
nucleon_file = pt.NucleonUnion(pathlib.Path("./nucleon") / selected_filename)
|
||||
nucleon_file = pt.NucleonUnion(
|
||||
pathlib.Path("./nucleon") / selected_filename
|
||||
)
|
||||
electron_file_path = pathlib.Path("./electron") / selected_filename
|
||||
if electron_file_path.exists():
|
||||
pass
|
||||
else:
|
||||
electron_file_path.touch()
|
||||
electron_file = pt.ElectronUnion(pathlib.Path("./electron") / selected_filename)
|
||||
# self.notify(f"已选择: {selected_filename}", timeout=2)
|
||||
electron_file = pt.ElectronUnion(
|
||||
pathlib.Path("./electron") / selected_filename
|
||||
)
|
||||
self.app.push_screen(PreparationScreen(nucleon_file, electron_file))
|
||||
|
||||
def action_quit_app(self) -> None:
|
||||
self.app.exit()
|
||||
|
||||
|
||||
class AppLauncher(App):
|
||||
CSS_PATH = "styles.tcss"
|
||||
TITLE = '潜进 - 辅助记忆程序'
|
||||
TITLE = "潜进 - 辅助记忆程序"
|
||||
BINDINGS = [("escape", "quit", "退出"), ("d", "toggle_dark", "改变色调")]
|
||||
SCREENS = {
|
||||
"file_selection_screen": FileSelectorScreen,
|
||||
}
|
||||
|
||||
def on_mount(self) -> None:
|
||||
#self.action_toggle_dark()
|
||||
self.push_screen("file_selection_screen")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = AppLauncher()
|
||||
app.run()
|
||||
app.run()
|
Reference in New Issue
Block a user