From a66cab8304e981accaf32fb10f87e39fb89ddb65 Mon Sep 17 00:00:00 2001 From: shuki Date: Sat, 7 Mar 2026 07:13:15 +0200 Subject: [PATCH] Fix back button: use Button without can_focus for Textual 2.x compat --- tui/screens/backup.py | 11 +++++++---- tui/screens/logs.py | 2 +- tui/screens/remotes.py | 11 +++++++---- tui/screens/restore.py | 11 +++++++---- tui/screens/retention.py | 11 +++++++---- tui/screens/running_tasks.py | 2 +- tui/screens/schedule.py | 11 +++++++---- tui/screens/settings.py | 11 +++++++---- tui/screens/snapshots.py | 11 +++++++---- tui/screens/targets.py | 11 +++++++---- 10 files changed, 58 insertions(+), 34 deletions(-) diff --git a/tui/screens/backup.py b/tui/screens/backup.py index e7c134a..981cba0 100644 --- a/tui/screens/backup.py +++ b/tui/screens/backup.py @@ -3,6 +3,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, Select from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from tui.config import list_conf_dir, has_targets, has_remotes from tui.jobs import job_manager from tui.widgets import ConfirmDialog, DocsPanel @@ -19,7 +20,7 @@ class BackupScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="backup-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Backup", id="screen-title") if not targets: yield Static("No sources configured. Add a source first.") @@ -67,9 +68,7 @@ class BackupScreen(Screen): pass def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-backup": + if event.button.id == "btn-backup": target_sel = self.query_one("#backup-target", Select) if not isinstance(target_sel.value, str): self.notify("Please select a source", severity="error") @@ -103,5 +102,9 @@ class BackupScreen(Screen): job_manager.start_job(self.app, job, "backup", "--all") self.app.switch_screen("running_tasks") + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/logs.py b/tui/screens/logs.py index 81d6ff5..eadabcb 100644 --- a/tui/screens/logs.py +++ b/tui/screens/logs.py @@ -91,7 +91,7 @@ class LogsScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="logs-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Logs", id="screen-title") yield DataTable(id="logs-table") with Horizontal(id="logs-buttons"): diff --git a/tui/screens/remotes.py b/tui/screens/remotes.py index 4981350..a72de35 100644 --- a/tui/screens/remotes.py +++ b/tui/screens/remotes.py @@ -3,6 +3,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, DataTable from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from textual import work from tui.config import list_conf_dir, parse_conf, CONFIG_DIR @@ -19,7 +20,7 @@ class RemotesScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="remotes-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Destinations", id="screen-title") yield DataTable(id="remotes-table") with Horizontal(id="remotes-buttons"): @@ -60,9 +61,7 @@ class RemotesScreen(Screen): return None def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-add": + if event.button.id == "btn-add": self.app.push_screen("remote_edit", callback=lambda _: self._refresh_table()) elif event.button.id == "btn-edit": name = self._selected_remote() @@ -122,5 +121,9 @@ class RemotesScreen(Screen): self.notify(f"Destination '{name}' deleted.") self._refresh_table() + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/restore.py b/tui/screens/restore.py index 634071b..657836c 100644 --- a/tui/screens/restore.py +++ b/tui/screens/restore.py @@ -3,6 +3,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, Select, Input, RadioSet, RadioButton, Switch from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from textual import work, on from tui.config import list_conf_dir, parse_conf, CONFIG_DIR @@ -22,7 +23,7 @@ class RestoreScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="restore-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Restore", id="screen-title") if not targets or not remotes: yield Static("Both sources and destinations must be configured for restore.") @@ -97,9 +98,7 @@ class RestoreScreen(Screen): self.notify("No snapshots found", severity="warning") def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-browse-dest": + if event.button.id == "btn-browse-dest": self.app.push_screen( FolderPicker("Select destination directory"), callback=self._dest_selected, @@ -157,5 +156,9 @@ class RestoreScreen(Screen): job_manager.start_job(self.app, job, *args) self.app.switch_screen("running_tasks") + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/retention.py b/tui/screens/retention.py index 9386fa4..f54c73e 100644 --- a/tui/screens/retention.py +++ b/tui/screens/retention.py @@ -3,6 +3,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, Select, Input from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from textual import work from tui.config import list_conf_dir, parse_conf, update_conf_key, CONFIG_DIR @@ -22,7 +23,7 @@ class RetentionScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="retention-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Retention Cleanup", id="screen-title") if not targets: yield Static("No sources configured.") @@ -45,9 +46,7 @@ class RetentionScreen(Screen): yield Footer() def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-cleanup": + if event.button.id == "btn-cleanup": target_sel = self.query_one("#ret-target", Select) if not isinstance(target_sel.value, str): self.notify("Select a source first", severity="error") @@ -92,5 +91,9 @@ class RetentionScreen(Screen): log_screen.write(f"\n[red]Cleanup failed (exit code {rc}).[/red]") log_screen.finish() + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/running_tasks.py b/tui/screens/running_tasks.py index 309959e..fb3c3a1 100644 --- a/tui/screens/running_tasks.py +++ b/tui/screens/running_tasks.py @@ -35,7 +35,7 @@ class RunningTasksScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="running-tasks-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Running Tasks", id="screen-title") yield DataTable(id="rt-table") with Horizontal(id="rt-buttons"): diff --git a/tui/screens/schedule.py b/tui/screens/schedule.py index e747aff..b4295b7 100644 --- a/tui/screens/schedule.py +++ b/tui/screens/schedule.py @@ -5,6 +5,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, DataTable from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from textual import work from tui.config import list_conf_dir, parse_conf, update_conf_key, CONFIG_DIR @@ -22,7 +23,7 @@ class ScheduleScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="schedule-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Schedules", id="screen-title") yield DataTable(id="sched-table") with Horizontal(id="sched-buttons"): @@ -98,9 +99,7 @@ class ScheduleScreen(Screen): return None def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-add": + if event.button.id == "btn-add": from tui.screens.schedule_edit import ScheduleEditScreen self.app.push_screen(ScheduleEditScreen(), callback=self._on_schedule_saved) elif event.button.id == "btn-edit": @@ -224,5 +223,9 @@ class ScheduleScreen(Screen): log_screen.write(stderr) log_screen.finish() + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/settings.py b/tui/screens/settings.py index 6f1eb71..094b1ce 100644 --- a/tui/screens/settings.py +++ b/tui/screens/settings.py @@ -3,6 +3,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, Input, Select from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from textual import work from tui.config import parse_conf, write_conf, CONFIG_DIR @@ -22,7 +23,7 @@ class SettingsScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="settings-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Settings", id="screen-title") with Vertical(classes="settings-section", id="section-general"): yield Static("Log Level:") @@ -91,9 +92,7 @@ class SettingsScreen(Screen): self.query_one("#section-web").border_title = "Web Dashboard" def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-save": + if event.button.id == "btn-save": self._save() elif event.button.id == "btn-test-email": self._save() @@ -141,5 +140,9 @@ class SettingsScreen(Screen): log_screen.write(stderr) log_screen.finish() + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/snapshots.py b/tui/screens/snapshots.py index 7ca2c1c..c8d11d8 100644 --- a/tui/screens/snapshots.py +++ b/tui/screens/snapshots.py @@ -6,6 +6,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, Select, DataTable from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from textual import work from tui.config import list_conf_dir @@ -33,7 +34,7 @@ class SnapshotsScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="snapshots-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Snapshots Browser", id="screen-title") if not targets or not remotes: yield Static("Sources and destinations must be configured to browse snapshots.") @@ -57,9 +58,7 @@ class SnapshotsScreen(Screen): pass def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-load": + if event.button.id == "btn-load": self._load_snapshots() elif event.button.id == "btn-browse": self._browse_snapshot() @@ -135,5 +134,9 @@ class SnapshotsScreen(Screen): browser = SnapshotBrowser(f"{target} / {snapshot}", files) self.app.push_screen(browser) + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen() diff --git a/tui/screens/targets.py b/tui/screens/targets.py index 3de981d..3bc0486 100644 --- a/tui/screens/targets.py +++ b/tui/screens/targets.py @@ -3,6 +3,7 @@ from textual.screen import Screen from textual.widgets import Header, Footer, Static, Button, DataTable from tui.widgets.header import GnizaHeader as Header # noqa: F811 from textual.containers import Vertical, Horizontal +from textual.events import Click from tui.config import list_conf_dir, parse_conf, CONFIG_DIR from tui.widgets import ConfirmDialog, DocsPanel @@ -17,7 +18,7 @@ class TargetsScreen(Screen): with Horizontal(classes="screen-with-docs"): with Vertical(id="targets-screen"): with Horizontal(id="title-bar"): - yield Button("← Back", id="btn-back", classes="back-btn", can_focus=False) + yield Button("← Back", id="btn-back", classes="back-btn") yield Static("Sources", id="screen-title") yield DataTable(id="targets-table") with Horizontal(id="targets-buttons"): @@ -52,9 +53,7 @@ class TargetsScreen(Screen): return None def on_button_pressed(self, event: Button.Pressed) -> None: - if event.button.id == "btn-back": - self.app.pop_screen() - elif event.button.id == "btn-add": + if event.button.id == "btn-add": self.app.push_screen("target_edit", callback=lambda _: self._refresh_table()) elif event.button.id == "btn-edit": name = self._selected_target() @@ -80,5 +79,9 @@ class TargetsScreen(Screen): self.notify(f"Source '{name}' deleted.") self._refresh_table() + def on_click(self, event: Click) -> None: + if event.widget.id == "btn-back": + self.app.pop_screen() + def action_go_back(self) -> None: self.app.pop_screen()