pygui: added simple error dialog call to app, also added blocking option for some error dialogs when needed
This commit is contained in:
parent
2387812a76
commit
b163b06596
4 changed files with 37 additions and 21 deletions
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import PhotoImage, font, ttk
|
from tkinter import PhotoImage, font, messagebox, ttk
|
||||||
from tkinter.ttk import Progressbar
|
from tkinter.ttk import Progressbar
|
||||||
from typing import Any, Dict, Optional, Type
|
from typing import Any, Dict, Optional, Type
|
||||||
|
|
||||||
|
@ -168,17 +168,30 @@ class Application(ttk.Frame):
|
||||||
def hide_info(self) -> None:
|
def hide_info(self) -> None:
|
||||||
self.infobar.grid_forget()
|
self.infobar.grid_forget()
|
||||||
|
|
||||||
def show_grpc_exception(self, title: str, e: grpc.RpcError) -> None:
|
def show_grpc_exception(
|
||||||
|
self, message: str, e: grpc.RpcError, blocking: bool = False
|
||||||
|
) -> None:
|
||||||
logging.exception("app grpc exception", exc_info=e)
|
logging.exception("app grpc exception", exc_info=e)
|
||||||
message = e.details()
|
dialog = ErrorDialog(self, "GRPC Exception", message, e.details())
|
||||||
self.show_error(title, message)
|
if blocking:
|
||||||
|
dialog.show()
|
||||||
|
else:
|
||||||
|
self.after(0, lambda: dialog.show())
|
||||||
|
|
||||||
def show_exception(self, title: str, e: Exception) -> None:
|
def show_exception(self, message: str, e: Exception) -> None:
|
||||||
logging.exception("app exception", exc_info=e)
|
logging.exception("app exception", exc_info=e)
|
||||||
self.show_error(title, str(e))
|
self.after(
|
||||||
|
0, lambda: ErrorDialog(self, "App Exception", message, str(e)).show()
|
||||||
|
)
|
||||||
|
|
||||||
def show_error(self, title: str, message: str) -> None:
|
def show_exception_data(self, title: str, message: str, details: str) -> None:
|
||||||
self.after(0, lambda: ErrorDialog(self, title, message).show())
|
self.after(0, lambda: ErrorDialog(self, title, message, details).show())
|
||||||
|
|
||||||
|
def show_error(self, title: str, message: str, blocking: bool = False) -> None:
|
||||||
|
if blocking:
|
||||||
|
messagebox.showerror(title, message, parent=self)
|
||||||
|
else:
|
||||||
|
self.after(0, lambda: messagebox.showerror(title, message, parent=self))
|
||||||
|
|
||||||
def on_closing(self) -> None:
|
def on_closing(self) -> None:
|
||||||
if self.toolbar.picker:
|
if self.toolbar.picker:
|
||||||
|
|
|
@ -41,7 +41,6 @@ from core.api.grpc.wrappers import (
|
||||||
from core.gui import nodeutils as nutils
|
from core.gui import nodeutils as nutils
|
||||||
from core.gui.appconfig import XMLS_PATH, CoreServer, Observer
|
from core.gui.appconfig import XMLS_PATH, CoreServer, Observer
|
||||||
from core.gui.dialogs.emaneinstall import EmaneInstallDialog
|
from core.gui.dialogs.emaneinstall import EmaneInstallDialog
|
||||||
from core.gui.dialogs.error import ErrorDialog
|
|
||||||
from core.gui.dialogs.mobilityplayer import MobilityPlayer
|
from core.gui.dialogs.mobilityplayer import MobilityPlayer
|
||||||
from core.gui.dialogs.sessions import SessionsDialog
|
from core.gui.dialogs.sessions import SessionsDialog
|
||||||
from core.gui.graph.edges import CanvasEdge
|
from core.gui.graph.edges import CanvasEdge
|
||||||
|
@ -418,10 +417,11 @@ class CoreClient:
|
||||||
if session_id:
|
if session_id:
|
||||||
session_ids = set(x.id for x in sessions)
|
session_ids = set(x.id for x in sessions)
|
||||||
if session_id not in session_ids:
|
if session_id not in session_ids:
|
||||||
dialog = ErrorDialog(
|
self.app.show_error(
|
||||||
self.app, "Join Session Error", f"{session_id} does not exist"
|
"Join Session Error",
|
||||||
|
f"{session_id} does not exist",
|
||||||
|
blocking=True,
|
||||||
)
|
)
|
||||||
dialog.show()
|
|
||||||
self.app.close()
|
self.app.close()
|
||||||
else:
|
else:
|
||||||
self.join_session(session_id)
|
self.join_session(session_id)
|
||||||
|
@ -433,8 +433,7 @@ class CoreClient:
|
||||||
dialog.show()
|
dialog.show()
|
||||||
except grpc.RpcError as e:
|
except grpc.RpcError as e:
|
||||||
logging.exception("core setup error")
|
logging.exception("core setup error")
|
||||||
dialog = ErrorDialog(self.app, "Setup Error", e.details())
|
self.app.show_grpc_exception("Setup Error", e, blocking=True)
|
||||||
dialog.show()
|
|
||||||
self.app.close()
|
self.app.close()
|
||||||
|
|
||||||
def edit_node(self, core_node: Node) -> None:
|
def edit_node(self, core_node: Node) -> None:
|
||||||
|
|
|
@ -13,9 +13,11 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
||||||
class ErrorDialog(Dialog):
|
class ErrorDialog(Dialog):
|
||||||
def __init__(self, app: "Application", title: str, details: str) -> None:
|
def __init__(
|
||||||
super().__init__(app, "CORE Exception")
|
self, app: "Application", title: str, message: str, details: str
|
||||||
self.title: str = title
|
) -> None:
|
||||||
|
super().__init__(app, title)
|
||||||
|
self.message: str = message
|
||||||
self.details: str = details
|
self.details: str = details
|
||||||
self.error_message: Optional[CodeText] = None
|
self.error_message: Optional[CodeText] = None
|
||||||
self.draw()
|
self.draw()
|
||||||
|
@ -25,13 +27,13 @@ class ErrorDialog(Dialog):
|
||||||
self.top.rowconfigure(1, weight=1)
|
self.top.rowconfigure(1, weight=1)
|
||||||
image = images.from_enum(ImageEnum.ERROR, width=images.ERROR_SIZE)
|
image = images.from_enum(ImageEnum.ERROR, width=images.ERROR_SIZE)
|
||||||
label = ttk.Label(
|
label = ttk.Label(
|
||||||
self.top, text=self.title, image=image, compound=tk.LEFT, anchor=tk.CENTER
|
self.top, text=self.message, image=image, compound=tk.LEFT, anchor=tk.CENTER
|
||||||
)
|
)
|
||||||
label.image = image
|
label.image = image
|
||||||
label.grid(sticky=tk.EW, pady=PADY)
|
label.grid(sticky=tk.W, pady=PADY)
|
||||||
self.error_message = CodeText(self.top)
|
self.error_message = CodeText(self.top)
|
||||||
self.error_message.text.insert("1.0", self.details)
|
self.error_message.text.insert("1.0", self.details)
|
||||||
self.error_message.text.config(state=tk.DISABLED)
|
self.error_message.text.config(state=tk.DISABLED)
|
||||||
self.error_message.grid(sticky=tk.NSEW, pady=PADY)
|
self.error_message.grid(sticky=tk.EW, pady=PADY)
|
||||||
button = ttk.Button(self.top, text="Close", command=lambda: self.destroy())
|
button = ttk.Button(self.top, text="Close", command=lambda: self.destroy())
|
||||||
button.grid(sticky=tk.EW)
|
button.grid(sticky=tk.EW)
|
||||||
|
|
|
@ -310,7 +310,9 @@ class Toolbar(ttk.Frame):
|
||||||
enable_buttons(self.design_frame, enabled=True)
|
enable_buttons(self.design_frame, enabled=True)
|
||||||
if exceptions:
|
if exceptions:
|
||||||
message = "\n".join(exceptions)
|
message = "\n".join(exceptions)
|
||||||
self.app.show_error("Start Session Error", message)
|
self.app.show_exception_data(
|
||||||
|
"Start Exception", "Session failed to start", message
|
||||||
|
)
|
||||||
|
|
||||||
def set_runtime(self) -> None:
|
def set_runtime(self) -> None:
|
||||||
enable_buttons(self.runtime_frame, enabled=True)
|
enable_buttons(self.runtime_frame, enabled=True)
|
||||||
|
|
Loading…
Reference in a new issue