pygui: added simple error dialog call to app, also added blocking option for some error dialogs when needed

This commit is contained in:
Blake Harnden 2021-02-19 10:35:59 -08:00
parent 2387812a76
commit b163b06596
4 changed files with 37 additions and 21 deletions

View file

@ -1,7 +1,7 @@
import logging
import math
import tkinter as tk
from tkinter import PhotoImage, font, ttk
from tkinter import PhotoImage, font, messagebox, ttk
from tkinter.ttk import Progressbar
from typing import Any, Dict, Optional, Type
@ -168,17 +168,30 @@ class Application(ttk.Frame):
def hide_info(self) -> None:
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)
message = e.details()
self.show_error(title, message)
dialog = ErrorDialog(self, "GRPC Exception", message, e.details())
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)
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:
self.after(0, lambda: ErrorDialog(self, title, message).show())
def show_exception_data(self, title: str, message: str, details: str) -> None:
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:
if self.toolbar.picker:

View file

@ -41,7 +41,6 @@ from core.api.grpc.wrappers import (
from core.gui import nodeutils as nutils
from core.gui.appconfig import XMLS_PATH, CoreServer, Observer
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.sessions import SessionsDialog
from core.gui.graph.edges import CanvasEdge
@ -418,10 +417,11 @@ class CoreClient:
if session_id:
session_ids = set(x.id for x in sessions)
if session_id not in session_ids:
dialog = ErrorDialog(
self.app, "Join Session Error", f"{session_id} does not exist"
self.app.show_error(
"Join Session Error",
f"{session_id} does not exist",
blocking=True,
)
dialog.show()
self.app.close()
else:
self.join_session(session_id)
@ -433,8 +433,7 @@ class CoreClient:
dialog.show()
except grpc.RpcError as e:
logging.exception("core setup error")
dialog = ErrorDialog(self.app, "Setup Error", e.details())
dialog.show()
self.app.show_grpc_exception("Setup Error", e, blocking=True)
self.app.close()
def edit_node(self, core_node: Node) -> None:

View file

@ -13,9 +13,11 @@ if TYPE_CHECKING:
class ErrorDialog(Dialog):
def __init__(self, app: "Application", title: str, details: str) -> None:
super().__init__(app, "CORE Exception")
self.title: str = title
def __init__(
self, app: "Application", title: str, message: str, details: str
) -> None:
super().__init__(app, title)
self.message: str = message
self.details: str = details
self.error_message: Optional[CodeText] = None
self.draw()
@ -25,13 +27,13 @@ class ErrorDialog(Dialog):
self.top.rowconfigure(1, weight=1)
image = images.from_enum(ImageEnum.ERROR, width=images.ERROR_SIZE)
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.grid(sticky=tk.EW, pady=PADY)
label.grid(sticky=tk.W, pady=PADY)
self.error_message = CodeText(self.top)
self.error_message.text.insert("1.0", self.details)
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.grid(sticky=tk.EW)

View file

@ -310,7 +310,9 @@ class Toolbar(ttk.Frame):
enable_buttons(self.design_frame, enabled=True)
if 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:
enable_buttons(self.runtime_frame, enabled=True)