Files
StreamLens/analyzer/tui/textual/widgets/progress_bar.py
2025-07-28 18:28:26 -04:00

121 lines
3.7 KiB
Python

"""
Progress Bar Widget for PCAP parsing progress
"""
from textual.widget import Widget
from textual.reactive import reactive
from rich.console import RenderableType
from rich.progress import Progress, BarColumn, TextColumn, TaskProgressColumn, MofNCompleteColumn, TimeRemainingColumn
from rich.text import Text
import time
class ParsingProgressBar(Widget):
"""Progress bar widget for PCAP parsing with rich formatting"""
DEFAULT_CSS = """
ParsingProgressBar {
height: 3;
margin: 1;
padding: 1;
background: $surface;
border: solid $accent;
}
"""
# Reactive attributes
progress = reactive(0.0)
total_packets = reactive(0)
processed_packets = reactive(0)
packets_per_second = reactive(0.0)
estimated_time_remaining = reactive(0.0)
is_complete = reactive(False)
is_visible = reactive(False)
error_message = reactive("")
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.start_time = None
def render(self) -> RenderableType:
"""Render the progress bar"""
if not self.is_visible:
return Text("")
if self.error_message:
return Text(f"❌ Error: {self.error_message}", style="red")
if self.is_complete:
elapsed = time.time() - self.start_time if self.start_time else 0
return Text(
f"✅ Parsing complete! {self.processed_packets:,} packets processed in {elapsed:.1f}s",
style="green"
)
# Create rich progress bar
progress = Progress(
TextColumn("[bold blue]Parsing PCAP..."),
BarColumn(bar_width=40),
TaskProgressColumn(),
MofNCompleteColumn(),
TextColumn(""),
TextColumn("{task.fields[rate]}"),
TextColumn(""),
TimeRemainingColumn(),
expand=False
)
# Format rate display
if self.packets_per_second >= 1000:
rate_str = f"{self.packets_per_second/1000:.1f}K pkt/s"
else:
rate_str = f"{self.packets_per_second:.0f} pkt/s"
task = progress.add_task(
"parsing",
total=self.total_packets,
completed=self.processed_packets,
rate=rate_str
)
return progress
def start_parsing(self, total_packets: int):
"""Start showing progress for parsing"""
self.total_packets = total_packets
self.processed_packets = 0
self.progress = 0.0
self.is_complete = False
self.is_visible = True
self.error_message = ""
self.start_time = time.time()
self.refresh()
def update_progress(self, processed: int, total: int, pps: float, eta: float):
"""Update progress values"""
self.processed_packets = processed
self.total_packets = total
self.packets_per_second = pps
self.estimated_time_remaining = eta
self.progress = (processed / total * 100) if total > 0 else 0
self.refresh()
def complete_parsing(self):
"""Mark parsing as complete"""
self.is_complete = True
self.refresh()
# Hide after 3 seconds
self.set_timer(3.0, self.hide_progress)
def show_error(self, error: str):
"""Show error message"""
self.error_message = error
self.is_visible = True
self.refresh()
# Hide after 5 seconds
self.set_timer(5.0, self.hide_progress)
def hide_progress(self):
"""Hide the progress bar"""
self.is_visible = False
self.refresh()