task | add ink support
This commit is contained in:
parent
9f9fd41851
commit
bf3b1fc456
13 changed files with 595 additions and 37 deletions
|
|
@ -3,7 +3,7 @@ from textual.screen import Screen
|
|||
from textual.widgets import Label, Input, Button, Header, Footer, DataTable
|
||||
from textual.containers import Vertical, Horizontal
|
||||
from textual.binding import Binding
|
||||
from .engine import PenTracker, Pen
|
||||
from .engine import PenTracker, Pen, InkTracker, Ink
|
||||
# --- TUI SCREENS ---
|
||||
|
||||
class PenFormScreen(Screen):
|
||||
|
|
@ -54,6 +54,50 @@ class PenFormScreen(Screen):
|
|||
self.tracker.save_data()
|
||||
self.dismiss(new_pen)
|
||||
|
||||
class InkFormScreen(Screen):
|
||||
"""A screen for adding or editing an ink."""
|
||||
|
||||
def __init__(self, ink_tracker, existing_ink=None):
|
||||
super().__init__()
|
||||
self.ink_tracker = ink_tracker
|
||||
self.existing_ink = existing_ink
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
with Vertical(id="form-container"):
|
||||
yield Label("🖋️ NEW INK" if not self.existing_ink else "✏️ EDIT INK")
|
||||
|
||||
for header in self.ink_tracker.headers:
|
||||
val = getattr(self.existing_ink, header) if self.existing_ink else ""
|
||||
yield Input(value=val, placeholder=header, id=header)
|
||||
|
||||
with Horizontal():
|
||||
yield Button("Save", variant="success", id="save_cmd")
|
||||
yield Button("Cancel", variant="error", id="cancel_cmd")
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
if event.button.id == "cancel_cmd":
|
||||
self.dismiss()
|
||||
return
|
||||
|
||||
new_data = {}
|
||||
for header in self.ink_tracker.headers:
|
||||
try:
|
||||
input_widget = self.query_one(f"#{header}", Input)
|
||||
new_data[header] = input_widget.value if input_widget.value.strip() else "N/A"
|
||||
except Exception:
|
||||
new_data[header] = "N/A"
|
||||
|
||||
new_ink = Ink(**new_data)
|
||||
|
||||
if self.existing_ink is not None and self.existing_ink in self.ink_tracker.inks:
|
||||
idx = self.ink_tracker.inks.index(self.existing_ink)
|
||||
self.ink_tracker.inks[idx] = new_ink
|
||||
else:
|
||||
self.ink_tracker.inks.append(new_ink)
|
||||
|
||||
self.ink_tracker.save_data()
|
||||
self.dismiss(new_ink)
|
||||
|
||||
class PenTrackerApp(App):
|
||||
"""The Main TUI Application."""
|
||||
|
||||
|
|
@ -89,7 +133,8 @@ class PenTrackerApp(App):
|
|||
|
||||
BINDINGS = [
|
||||
Binding("d", "delete_selected", "Delete Selected"),
|
||||
Binding("a", "add_new", "Add New Pen"),
|
||||
Binding("a", "add_new", "Add New"),
|
||||
Binding("i", "toggle_mode", "Toggle Pens/Inks"),
|
||||
Binding("q", "quit", "Quit"),
|
||||
]
|
||||
|
||||
|
|
@ -100,29 +145,46 @@ class PenTrackerApp(App):
|
|||
|
||||
def on_mount(self) -> None:
|
||||
self.tracker = PenTracker()
|
||||
self.ink_tracker = InkTracker()
|
||||
self.mode = "pens" # "pens" or "inks"
|
||||
self._refresh_table()
|
||||
|
||||
def _refresh_table(self):
|
||||
table = self.query_one("#pen_table", DataTable)
|
||||
table.clear(columns=True)
|
||||
|
||||
display_cols = ['Make', 'Model', 'Nib', 'Nib-Material', 'Body','Cap', 'Current-Ink', 'Inked-date', 'Notes']
|
||||
table.add_columns(*display_cols)
|
||||
if self.mode == "pens":
|
||||
display_cols = ['Make', 'Model', 'Nib', 'Nib-Material', 'Body','Cap', 'Current-Ink', 'Inked-date', 'Notes']
|
||||
table.add_columns(*display_cols)
|
||||
items = self.tracker.pens
|
||||
else: # inks
|
||||
display_cols = ['Vendor', 'Name', 'Color', 'Purchased', 'Size', 'Notes']
|
||||
table.add_columns(*display_cols)
|
||||
items = self.ink_tracker.inks
|
||||
|
||||
for idx, pen in enumerate(self.tracker.pens):
|
||||
row_values = [getattr(pen, c.replace('-','_')) for c in display_cols]
|
||||
# We use the index as the row key to track items accurately
|
||||
for idx, item in enumerate(items):
|
||||
if self.mode == "pens":
|
||||
row_values = [getattr(item, c.replace('-','_')) for c in display_cols]
|
||||
else:
|
||||
row_values = [getattr(item, c) for c in display_cols]
|
||||
table.add_row(*row_values, key=str(idx))
|
||||
|
||||
def action_add_new(self) -> None:
|
||||
form = PenFormScreen(self.tracker)
|
||||
if self.mode == "pens":
|
||||
form = PenFormScreen(self.tracker)
|
||||
else:
|
||||
form = InkFormScreen(self.ink_tracker)
|
||||
self.push_screen(form, self.handle_form_result)
|
||||
|
||||
def action_edit_selected(self, index_str: str):
|
||||
try:
|
||||
idx = int(index_str)
|
||||
existing_pen = self.tracker.pens[idx]
|
||||
form = PenFormScreen(self.tracker, existing_pen=existing_pen)
|
||||
if self.mode == "pens":
|
||||
existing_item = self.tracker.pens[idx]
|
||||
form = PenFormScreen(self.tracker, existing_item)
|
||||
else:
|
||||
existing_item = self.ink_tracker.inks[idx]
|
||||
form = InkFormScreen(self.ink_tracker, existing_item)
|
||||
self.push_screen(form, self.handle_form_result)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
|
@ -135,16 +197,26 @@ class PenTrackerApp(App):
|
|||
def action_delete_selected(self) -> None:
|
||||
table = self.query_one("#pen_table", DataTable)
|
||||
try:
|
||||
# Accessing via the table's current cursor
|
||||
table = self.query_one("#pen_table", DataTable)
|
||||
row_node = table.get_row_at_cursor()
|
||||
idx = int(row_node.key.value)
|
||||
removed = self.tracker.pens.pop(idx)
|
||||
self.tracker.save_data()
|
||||
if self.mode == "pens":
|
||||
removed = self.tracker.pens.pop(idx)
|
||||
self.tracker.save_data()
|
||||
self.notify(f"Deleted {removed.Make}", title="Removed")
|
||||
else:
|
||||
removed = self.ink_tracker.inks.pop(idx)
|
||||
self.ink_tracker.save_data()
|
||||
self.notify(f"Deleted {removed.Name}", title="Removed")
|
||||
self._refresh_table()
|
||||
self.notify(f"Deleted {removed.Make}", title="Removed")
|
||||
except Exception:
|
||||
self.notify("No pen selected to delete", title="Error", severity="error")
|
||||
self.notify("No item selected to delete", title="Error", severity="error")
|
||||
|
||||
def action_toggle_mode(self) -> None:
|
||||
self.mode = "inks" if self.mode == "pens" else "pens"
|
||||
self._refresh_table()
|
||||
mode_name = "Pens" if self.mode == "pens" else "Inks"
|
||||
self.notify(f"Switched to {mode_name} mode", title="Mode Changed")
|
||||
|
||||
def on_data_table_cell_selected(self, event: DataTable.CellSelected) -> None:
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue