59 lines
1.7 KiB
Python
59 lines
1.7 KiB
Python
import logging
|
|
import threading
|
|
import time
|
|
import tkinter as tk
|
|
from typing import TYPE_CHECKING, Any, Callable, Optional
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
if TYPE_CHECKING:
|
|
from core.gui.app import Application
|
|
|
|
|
|
class ProgressTask:
|
|
def __init__(
|
|
self,
|
|
app: "Application",
|
|
title: str,
|
|
task: Callable,
|
|
callback: Callable = None,
|
|
args: tuple[Any] = None,
|
|
):
|
|
self.app: "Application" = app
|
|
self.title: str = title
|
|
self.task: Callable = task
|
|
self.callback: Callable = callback
|
|
if args is None:
|
|
args = ()
|
|
self.args: tuple[Any] = args
|
|
self.time: Optional[float] = None
|
|
|
|
def start(self) -> None:
|
|
self.app.progress.grid(sticky=tk.EW, columnspan=2)
|
|
self.app.progress.start()
|
|
self.time = time.perf_counter()
|
|
thread = threading.Thread(target=self.run, daemon=True)
|
|
thread.start()
|
|
|
|
def run(self) -> None:
|
|
try:
|
|
values = self.task(*self.args)
|
|
if values is None:
|
|
values = ()
|
|
elif values is not None and not isinstance(values, tuple):
|
|
values = (values,)
|
|
if self.callback:
|
|
self.app.after(0, self.callback, *values)
|
|
except Exception as e:
|
|
logger.exception("progress task exception")
|
|
self.app.show_exception("Task Error", e)
|
|
finally:
|
|
self.app.after(0, self.complete)
|
|
|
|
def complete(self) -> None:
|
|
self.app.progress.stop()
|
|
self.app.progress.grid_forget()
|
|
total = time.perf_counter() - self.time
|
|
self.time = None
|
|
message = f"{self.title} ran for {total:.3f} seconds"
|
|
self.app.statusbar.set_status(message)
|