replace tkinter errormessage with custom create error dialog

This commit is contained in:
Huy Pham 2020-02-05 15:09:33 -08:00
parent 9216683902
commit 0407645061
15 changed files with 132 additions and 56 deletions

View file

@ -335,7 +335,7 @@ class CoreClient:
self.parse_metadata(response.config)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
# update ui to represent current state
self.app.after(0, self.app.joined_session_update)
@ -423,16 +423,21 @@ class CoreClient:
)
self.join_session(response.session_id, query_location=False)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
def delete_session(self, session_id: int = None):
def delete_session(self, session_id: int = None, parent_frame=None):
if session_id is None:
session_id = self.session_id
try:
response = self.client.delete_session(session_id)
logging.info("deleted session(%s), Result: %s", session_id, response)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
# use the right master widget so the error dialog displays right on top of it
master = self.app
if parent_frame:
master = parent_frame
print("stop session error")
self.app.after(0, show_grpc_error, e, master, self.app)
def set_up(self):
"""
@ -468,7 +473,7 @@ class CoreClient:
x.node_type: set(x.services) for x in response.defaults
}
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
self.app.close()
def edit_node(self, core_node: core_pb2.Node):
@ -477,7 +482,7 @@ class CoreClient:
self.session_id, core_node.id, core_node.position, source=GUI_SOURCE
)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
def start_session(self) -> core_pb2.StartSessionResponse:
nodes = [x.core_node for x in self.canvas_nodes.values()]
@ -521,7 +526,7 @@ class CoreClient:
if response.result:
self.set_metadata()
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
return response
def stop_session(self, session_id: int = None) -> core_pb2.StartSessionResponse:
@ -532,7 +537,7 @@ class CoreClient:
response = self.client.stop_session(session_id)
logging.info("stopped session(%s), result: %s", session_id, response)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
return response
def show_mobility_players(self):
@ -577,7 +582,7 @@ class CoreClient:
logging.info("launching terminal %s", cmd)
os.system(cmd)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
def save_xml(self, file_path: str):
"""
@ -590,7 +595,7 @@ class CoreClient:
response = self.client.save_xml(self.session_id, file_path)
logging.info("saved xml file %s, result: %s", file_path, response)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
def open_xml(self, file_path: str):
"""
@ -601,7 +606,7 @@ class CoreClient:
logging.info("open xml file %s, response: %s", file_path, response)
self.join_session(response.session_id)
except grpc.RpcError as e:
self.app.after(0, show_grpc_error, e)
self.app.after(0, show_grpc_error, e, self.app, self.app)
def get_node_service(
self, node_id: int, service_name: str

View file

@ -65,8 +65,13 @@ class ConfigServiceConfigDialog(Dialog):
self.config_frame = None
self.default_config = None
self.config = None
self.has_error = False
self.load()
self.draw()
if not self.has_error:
self.draw()
def load(self):
try:
@ -106,7 +111,8 @@ class ConfigServiceConfigDialog(Dialog):
self.modified_files.add(file)
self.temp_service_files[file] = data
except grpc.RpcError as e:
show_grpc_error(e)
self.has_error = True
show_grpc_error(e, self.app, self.app)
def draw(self):
self.top.columnconfigure(0, weight=1)
@ -327,7 +333,7 @@ class ConfigServiceConfigDialog(Dialog):
all_current = current_listbox.get(0, tk.END)
current_listbox.itemconfig(all_current.index(self.service_name), bg="green")
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.top, self.app)
self.destroy()
def handle_template_changed(self, event: tk.Event):

View file

@ -65,14 +65,17 @@ class EmaneModelDialog(Dialog):
self.model = f"emane_{model}"
self.interface = interface
self.config_frame = None
self.error = False
try:
self.config = self.app.core.get_emane_model_config(
self.node.id, self.model, self.interface
)
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.app, self.app)
self.error = True
self.destroy()
self.draw()
if not self.error:
self.draw()
def draw(self):
self.top.columnconfigure(0, weight=1)
@ -225,7 +228,8 @@ class EmaneConfigDialog(Dialog):
dialog = EmaneModelDialog(
self, self.app, self.canvas_node.core_node, model_name
)
dialog.show()
if not dialog.error:
dialog.show()
def emane_model_change(self, event: tk.Event):
"""

View file

@ -29,12 +29,14 @@ class MobilityConfigDialog(Dialog):
self.canvas_node = canvas_node
self.node = canvas_node.core_node
self.config_frame = None
self.has_error = False
try:
self.config = self.app.core.get_mobility_config(self.node.id)
self.draw()
except grpc.RpcError as e:
show_grpc_error(e)
self.has_error = True
show_grpc_error(e, self.app, self.app)
self.destroy()
self.draw()
def draw(self):
self.top.columnconfigure(0, weight=1)

View file

@ -153,7 +153,7 @@ class MobilityPlayerDialog(Dialog):
session_id, self.node.id, MobilityAction.START
)
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.top, self.app)
def click_pause(self):
self.set_pause()
@ -163,7 +163,7 @@ class MobilityPlayerDialog(Dialog):
session_id, self.node.id, MobilityAction.PAUSE
)
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.top, self.app)
def click_stop(self):
self.set_stop()
@ -173,4 +173,4 @@ class MobilityPlayerDialog(Dialog):
session_id, self.node.id, MobilityAction.STOP
)
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.top, self.app)

View file

@ -124,7 +124,8 @@ class NodeConfigServiceDialog(Dialog):
service_name=self.current.listbox.get(current_selection[0]),
node_id=self.node_id,
)
dialog.show()
if not dialog.has_error:
dialog.show()
else:
messagebox.showinfo(
"Node service configuration", "Select a service to configure"

View file

@ -140,7 +140,12 @@ class NodeServiceDialog(Dialog):
service_name=self.current.listbox.get(current_selection[0]),
node_id=self.node_id,
)
dialog.show()
# if error occurred when creating ServiceConfigDialog, don't show the dialog
if not dialog.error:
dialog.show()
else:
dialog.destroy()
else:
messagebox.showinfo(
"Node service configuration", "Select a service to configure"

View file

@ -64,10 +64,16 @@ class ServiceConfigDialog(Dialog):
self.original_service_files = {}
self.temp_service_files = {}
self.modified_files = set()
self.load()
self.draw()
def load(self):
self.error = True
load_result = self.load()
if load_result:
self.draw()
self.error = False
def load(self) -> bool:
result = False
try:
self.app.core.create_nodes_and_links()
default_config = self.app.core.get_node_service(
@ -108,8 +114,10 @@ class ServiceConfigDialog(Dialog):
):
for file, data in file_configs[self.node_id][self.service_name].items():
self.temp_service_files[file] = data
result = True
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.master, self.app)
return result
def draw(self):
self.top.columnconfigure(0, weight=1)
@ -444,7 +452,7 @@ class ServiceConfigDialog(Dialog):
all_current = current_listbox.get(0, tk.END)
current_listbox.itemconfig(all_current.index(self.service_name), bg="green")
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.top, self.app)
self.destroy()
def display_service_file_data(self, event: tk.Event):

View file

@ -17,8 +17,10 @@ class SessionOptionsDialog(Dialog):
def __init__(self, master: "Application", app: "Application"):
super().__init__(master, app, "Session Options", modal=True)
self.config_frame = None
self.has_error = False
self.config = self.get_config()
self.draw()
if not self.has_error:
self.draw()
def get_config(self):
try:
@ -26,7 +28,8 @@ class SessionOptionsDialog(Dialog):
response = self.app.core.client.get_session_options(session_id)
return response.config
except grpc.RpcError as e:
show_grpc_error(e)
self.has_error = True
show_grpc_error(e, self.app, self.app)
self.destroy()
def draw(self):
@ -53,5 +56,5 @@ class SessionOptionsDialog(Dialog):
response = self.app.core.client.set_session_options(session_id, config)
logging.info("saved session config: %s", response)
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.top, self.app)
self.destroy()

View file

@ -25,8 +25,10 @@ class SessionsDialog(Dialog):
self.selected = False
self.selected_id = None
self.tree = None
self.error = False
self.sessions = self.get_sessions()
self.draw()
if not self.error:
self.draw()
def get_sessions(self) -> Iterable[core_pb2.SessionSummary]:
try:
@ -34,7 +36,8 @@ class SessionsDialog(Dialog):
logging.info("sessions: %s", response)
return response.sessions
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.app, self.app)
self.error = True
self.destroy()
def draw(self):
@ -211,7 +214,7 @@ class SessionsDialog(Dialog):
item = self.tree.selection()
if item:
sid = int(self.tree.item(item, "text"))
self.app.core.delete_session(sid)
self.app.core.delete_session(sid, self.top)
self.tree.delete(item[0])
if sid == self.app.core.session_id:
self.click_new()

View file

@ -27,12 +27,14 @@ class WlanConfigDialog(Dialog):
self.canvas_node = canvas_node
self.node = canvas_node.core_node
self.config_frame = None
self.error = False
try:
self.config = self.app.core.get_wlan_config(self.node.id)
self.draw()
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.app, self.app)
self.error = True
self.destroy()
self.draw()
def draw(self):
self.top.columnconfigure(0, weight=1)

View file

@ -1,12 +1,32 @@
from tkinter import messagebox
from typing import TYPE_CHECKING
from core.gui.dialogs.dialog import Dialog
from core.gui.widgets import CodeText
if TYPE_CHECKING:
import grpc
from core.gui.app import Application
def show_grpc_error(e: "grpc.RpcError"):
class ErrorDialog(Dialog):
def __init__(self, master, app: "Application", title: str, details: str):
super().__init__(master, app, title, modal=True)
self.error_message = None
self.details = details
self.draw()
def draw(self):
self.top.columnconfigure(0, weight=1)
self.top.rowconfigure(0, weight=1)
self.error_message = CodeText(self.top)
self.error_message.text.insert("1.0", self.details)
self.error_message.text.config(state="disabled")
self.error_message.grid(row=0, column=0, sticky="nsew")
def show_grpc_error(e: "grpc.RpcError", master, app: "Application"):
title = [x.capitalize() for x in e.code().name.lower().split("_")]
title = " ".join(title)
title = f"GRPC {title}"
messagebox.showerror(title, e.details())
dialog = ErrorDialog(master, app, title, e.details())
dialog.show()

View file

@ -165,7 +165,7 @@ class CanvasNode:
output = self.app.core.run(self.core_node.id)
self.tooltip.text.set(output)
except grpc.RpcError as e:
show_grpc_error(e)
show_grpc_error(e, self.app, self.app)
def on_leave(self, event: tk.Event):
self.tooltip.on_leave(event)
@ -240,12 +240,14 @@ class CanvasNode:
def show_wlan_config(self):
self.canvas.context = None
dialog = WlanConfigDialog(self.app, self.app, self)
dialog.show()
if not dialog.error:
dialog.show()
def show_mobility_config(self):
self.canvas.context = None
dialog = MobilityConfigDialog(self.app, self.app, self)
dialog.show()
if not dialog.has_error:
dialog.show()
def show_mobility_player(self):
self.canvas.context = None

View file

@ -9,6 +9,8 @@ import webbrowser
from tkinter import filedialog, messagebox
from typing import TYPE_CHECKING
import grpc
from core.gui.appconfig import XMLS_PATH
from core.gui.dialogs.about import AboutDialog
from core.gui.dialogs.canvassizeandscale import SizeAndScaleDialog
@ -32,12 +34,18 @@ class MenuAction:
self.app = app
self.canvas = app.canvas
def cleanup_old_session(self, session_id):
response = self.app.core.stop_session()
self.app.core.delete_session(session_id)
logging.info(
"Stop session(%s) and delete it, result: %s", session_id, response.result
)
def cleanup_old_session(self, session_id: int):
try:
res = self.app.core.client.get_session(session_id)
logging.debug("retrieve session(%s), %s", session_id, res)
stop_response = self.app.core.stop_session()
logging.debug("stop session(%s), result: %s", session_id, stop_response)
delete_response = self.app.core.delete_session(session_id)
logging.debug(
"deleted session(%s), result: %s", session_id, delete_response
)
except grpc.RpcError:
logging.debug("session is not alive")
def prompt_save_running_session(self, quitapp: bool = False):
"""
@ -121,7 +129,8 @@ class MenuAction:
def session_options(self):
logging.debug("Click options")
dialog = SessionOptionsDialog(self.app, self.app)
dialog.show()
if not dialog.has_error:
dialog.show()
def session_change_sessions(self):
logging.debug("Click change sessions")

View file

@ -2,7 +2,7 @@ import logging
import time
import tkinter as tk
from functools import partial
from tkinter import messagebox, ttk
from tkinter import ttk
from tkinter.font import Font
from typing import TYPE_CHECKING, Callable
@ -262,9 +262,13 @@ class Toolbar(ttk.Frame):
self.set_runtime()
self.app.core.set_metadata()
self.app.core.show_mobility_players()
else:
message = "\n".join(response.exceptions)
messagebox.showerror("Start Error", message)
# else:
# message = "\n".join(response.exceptions)
# print("start error")
# print(response)
# dialog = ErrorDialog(self.app, self.app, "Start ERROR", message)
# dialog.show()
# messagebox.showerror("Start Error", message)
def set_runtime(self):
self.runtime_frame.tkraise()
@ -431,8 +435,10 @@ class Toolbar(ttk.Frame):
message = f"Stopped in {total:.3f} seconds"
self.app.statusbar.set_status(message)
self.app.canvas.stopped_session()
if not response.result:
messagebox.showerror("Stop Error", "Errors stopping session")
# if not response.result:
# dialog = ErrorDialog(self.app, self.app, "Stop ERROR", "Error stopping session")
# dialog.show()
# # messagebox.showerror("Stop Error", "Errors stopping session")
def update_annotation(self, image: "ImageTk.PhotoImage", shape_type: ShapeType):
logging.debug("clicked annotation: ")