summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mod.css16
-rwxr-xr-xmod.py49
-rw-r--r--modui/filetable.py44
3 files changed, 56 insertions, 53 deletions
diff --git a/mod.css b/mod.css
index c001ef1..5563832 100644
--- a/mod.css
+++ b/mod.css
@@ -1,5 +1,6 @@
#ftable {
width: 1fr;
+ height: 100%;
}
#infopane {
@@ -10,7 +11,7 @@
#finfo {
background: $boost;
- height: 12;
+ height: 14;
width: 1fr;
box-sizing: content-box;
}
@@ -27,20 +28,9 @@
width: 1fr;
}
-#filter_container {
- height: auto;
- display: none;
-}
-
-#filter_label {
- content-align: right middle;
- height: 1fr;
- width: 20%;
- margin: 0 1 0 2;
-}
-
#filter_input {
width: 1fr;
+ display: none;
}
Notification {
diff --git a/mod.py b/mod.py
index 0748a42..df011fe 100755
--- a/mod.py
+++ b/mod.py
@@ -5,7 +5,7 @@ from sys import stdout
import time
from textual.app import App, ComposeResult
-from textual.widgets import DataTable, Header, Footer, TextLog, Static, Input
+from textual.widgets import DataTable, Header, Footer, RichLog, Static, Input
from textual.containers import Horizontal, Vertical
from textual.screen import Screen
from textual import log
@@ -20,13 +20,13 @@ fhost_app.app_context().push()
class NullptrMod(Screen):
BINDINGS = [
("q", "quit_app", "Quit"),
- ("f1", "filter(1, 'Lookup name:')", "Lookup name"),
- ("f2", "filter(2, 'Filter IP address:')", "Filter IP"),
- ("f3", "filter(3, 'Filter MIME Type:')", "Filter MIME"),
- ("f4", "filter(4, 'Filter extension:')", "Filter Ext."),
+ ("f1", "filter(1, 'Name')", "Lookup name"),
+ ("f2", "filter(2, 'IP address')", "Filter IP"),
+ ("f3", "filter(3, 'MIME Type')", "Filter MIME"),
+ ("f4", "filter(4, 'Extension')", "Filter Ext."),
("f5", "refresh", "Refresh"),
("f6", "filter_clear", "Clear filter"),
- ("f7", "filter(5, 'Filter user agent:')", "Filter UA"),
+ ("f7", "filter(5, 'User agent')", "Filter UA"),
("r", "remove_file(False)", "Remove file"),
("ctrl+r", "remove_file(True)", "Ban file"),
("p", "ban_ip(False)", "Ban IP"),
@@ -42,29 +42,28 @@ class NullptrMod(Screen):
ftable.watch_query(None, None)
def action_filter_clear(self):
- self.query_one("#filter_container").display = False
+ self.finput.display = False
ftable = self.query_one("#ftable")
ftable.focus()
ftable.query = ftable.base_query
def action_filter(self, fcol: int, label: str):
- self.query_one("#filter_label").update(label)
- finput = self.query_one("#filter_input")
+ self.finput.placeholder = label
+ self.finput.display = True
+ self.finput.focus()
self.filter_col = fcol
- self.query_one("#filter_container").display = True
- finput.focus()
self._refresh_layout()
if self.current_file:
match fcol:
- case 1: finput.value = ""
- case 2: finput.value = self.current_file.addr
- case 3: finput.value = self.current_file.mime
- case 4: finput.value = self.current_file.ext
- case 5: finput.value = self.current_file.ua or ""
+ case 1: self.finput.value = ""
+ case 2: self.finput.value = self.current_file.addr
+ case 3: self.finput.value = self.current_file.mime
+ case 4: self.finput.value = self.current_file.ext
+ case 5: self.finput.value = self.current_file.ua or ""
def on_input_submitted(self, message: Input.Submitted) -> None:
- self.query_one("#filter_container").display = False
+ self.finput.display = False
ftable = self.query_one("#ftable")
ftable.focus()
@@ -122,13 +121,13 @@ class NullptrMod(Screen):
def compose(self) -> ComposeResult:
yield Header()
yield Horizontal(
- FileTable(id="ftable", zebra_stripes=True),
+ FileTable(id="ftable", zebra_stripes=True, cursor_type="row"),
Vertical(
- DataTable(id="finfo", show_header=False),
+ DataTable(id="finfo", show_header=False, cursor_type="none"),
MpvWidget(id="mpv"),
- TextLog(id="ftextlog"),
+ RichLog(id="ftextlog", auto_scroll=False),
id="infopane"))
- yield Horizontal(Static("Filter:", id="filter_label"), Input(id="filter_input"), id="filter_container")
+ yield Input(id="filter_input")
yield Footer()
def on_mount(self) -> None:
@@ -143,6 +142,8 @@ class NullptrMod(Screen):
self.mpvw = self.query_one("#mpv")
self.ftlog = self.query_one("#ftextlog")
+ self.finput = self.query_one("#filter_input")
+
self.mimehandler = mime.MIMEHandler()
self.mimehandler.register(mime.MIMECategory.Archive, self.handle_libarchive)
self.mimehandler.register(mime.MIMECategory.Text, self.handle_text)
@@ -261,13 +262,11 @@ class NullptrMod(Screen):
])
self.mpvw.stop_mpv(True)
- self.ftlog.remove()
- self.query_one("#infopane").mount(TextLog(id="ftextlog"))
- self.ftlog = self.query_one("#ftextlog")
+ self.ftlog.clear()
if f.getpath().is_file():
self.mimehandler.handle(f.mime, f.ext)
- self.ftlog.scroll_home(animate=False)
+ self.ftlog.scroll_to(x=0, y=0, animate=False)
class NullptrModApp(App):
CSS_PATH = "mod.css"
diff --git a/modui/filetable.py b/modui/filetable.py
index 7be0f1b..879eed0 100644
--- a/modui/filetable.py
+++ b/modui/filetable.py
@@ -1,6 +1,6 @@
from textual.widgets import DataTable, Static
from textual.reactive import Reactive
-from textual.message import Message, MessageTarget
+from textual.message import Message
from textual import events, log
from jinja2.filters import do_filesizeformat
@@ -21,9 +21,9 @@ class FileTable(DataTable):
self.query = self.base_query
class Selected(Message):
- def __init__(self, sender: MessageTarget, f: File) -> None:
+ def __init__(self, f: File) -> None:
self.file = f
- super().__init__(sender)
+ super().__init__()
def watch_order_col(self, old, value) -> None:
self.watch_query(None, None)
@@ -44,25 +44,39 @@ class FileTable(DataTable):
)
if (self.query):
- self.clear()
+
order = FileTable.colmap[self.order_col]
q = self.query
if order: q = q.order_by(order.desc() if self.order_desc else order, File.id)
- self.add_rows(map(fmt_file, q.limit(self.limit)))
+ qres = list(map(fmt_file, q.limit(self.limit)))
+
+ ri = 0
+ row = self.cursor_coordinate.row
+ if row < self.row_count and row >= 0:
+ ri = int(self.get_row_at(row)[0])
+
+ self.clear()
+ self.add_rows(qres)
+
+ for i, v in enumerate(qres):
+ if int(v[0]) == ri:
+ self.move_cursor(row=i)
+ break
+
+ self.on_selected()
- def _scroll_cursor_in_to_view(self, animate: bool = False) -> None:
- region = self._get_cell_region(self.cursor_row, 0)
- spacing = self._get_cell_border()
- self.scroll_to_region(region, animate=animate, spacing=spacing)
+ def on_selected(self) -> Selected:
+ row = self.cursor_coordinate.row
+ if row < self.row_count and row >= 0:
+ f = File.query.get(int(self.get_row_at(row)[0]))
+ self.post_message(self.Selected(f))
- async def watch_cursor_cell(self, old, value) -> None:
- super().watch_cursor_cell(old, value)
- if value[0] < len(self.data) and value[0] >= 0:
- f = File.query.get(int(self.data[value[0]][0]))
- await self.emit(self.Selected(self, f))
+ def watch_cursor_coordinate(self, old, value) -> None:
+ super().watch_cursor_coordinate(old, value)
+ if old != value:
+ self.on_selected()
def on_click(self, event: events.Click) -> None:
- super().on_click(event)
meta = self.get_style_at(event.x, event.y).meta
if meta:
if meta["row"] == -1: