progress?
This commit is contained in:
121
analyzer/tui/textual/widgets/progress_bar.py
Normal file
121
analyzer/tui/textual/widgets/progress_bar.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""
|
||||
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()
|
||||
Reference in New Issue
Block a user