pygui: updated ConfigFrame to have a disabled display option, updated nodes to stil show emane config during runtime, updated emane dialog and config dialogs to be in a viewable but disabled state during runtime
This commit is contained in:
parent
527d34e374
commit
344f35e93e
3 changed files with 42 additions and 23 deletions
|
@ -24,12 +24,15 @@ class GlobalEmaneDialog(Dialog):
|
||||||
def __init__(self, master: tk.BaseWidget, app: "Application") -> None:
|
def __init__(self, master: tk.BaseWidget, app: "Application") -> None:
|
||||||
super().__init__(app, "EMANE Configuration", master=master)
|
super().__init__(app, "EMANE Configuration", master=master)
|
||||||
self.config_frame: Optional[ConfigFrame] = None
|
self.config_frame: Optional[ConfigFrame] = None
|
||||||
|
self.enabled: bool = not self.app.core.is_runtime()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self) -> None:
|
def draw(self) -> None:
|
||||||
self.top.columnconfigure(0, weight=1)
|
self.top.columnconfigure(0, weight=1)
|
||||||
self.top.rowconfigure(0, weight=1)
|
self.top.rowconfigure(0, weight=1)
|
||||||
self.config_frame = ConfigFrame(self.top, self.app, self.app.core.emane_config)
|
self.config_frame = ConfigFrame(
|
||||||
|
self.top, self.app, self.app.core.emane_config, self.enabled
|
||||||
|
)
|
||||||
self.config_frame.draw_config()
|
self.config_frame.draw_config()
|
||||||
self.config_frame.grid(sticky="nsew", pady=PADY)
|
self.config_frame.grid(sticky="nsew", pady=PADY)
|
||||||
self.draw_spacer()
|
self.draw_spacer()
|
||||||
|
@ -40,9 +43,9 @@ class GlobalEmaneDialog(Dialog):
|
||||||
frame.grid(sticky="ew")
|
frame.grid(sticky="ew")
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
frame.columnconfigure(i, weight=1)
|
frame.columnconfigure(i, weight=1)
|
||||||
button = ttk.Button(frame, text="Apply", command=self.click_apply)
|
state = tk.NORMAL if self.enabled else tk.DISABLED
|
||||||
|
button = ttk.Button(frame, text="Apply", command=self.click_apply, state=state)
|
||||||
button.grid(row=0, column=0, sticky="ew", padx=PADX)
|
button.grid(row=0, column=0, sticky="ew", padx=PADX)
|
||||||
|
|
||||||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
button.grid(row=0, column=1, sticky="ew")
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
@ -68,6 +71,7 @@ class EmaneModelDialog(Dialog):
|
||||||
self.model: str = f"emane_{model}"
|
self.model: str = f"emane_{model}"
|
||||||
self.iface_id: int = iface_id
|
self.iface_id: int = iface_id
|
||||||
self.config_frame: Optional[ConfigFrame] = None
|
self.config_frame: Optional[ConfigFrame] = None
|
||||||
|
self.enabled: bool = not self.app.core.is_runtime()
|
||||||
self.has_error: bool = False
|
self.has_error: bool = False
|
||||||
try:
|
try:
|
||||||
config = self.canvas_node.emane_model_configs.get(
|
config = self.canvas_node.emane_model_configs.get(
|
||||||
|
@ -87,7 +91,7 @@ class EmaneModelDialog(Dialog):
|
||||||
def draw(self) -> None:
|
def draw(self) -> None:
|
||||||
self.top.columnconfigure(0, weight=1)
|
self.top.columnconfigure(0, weight=1)
|
||||||
self.top.rowconfigure(0, weight=1)
|
self.top.rowconfigure(0, weight=1)
|
||||||
self.config_frame = ConfigFrame(self.top, self.app, self.config)
|
self.config_frame = ConfigFrame(self.top, self.app, self.config, self.enabled)
|
||||||
self.config_frame.draw_config()
|
self.config_frame.draw_config()
|
||||||
self.config_frame.grid(sticky="nsew", pady=PADY)
|
self.config_frame.grid(sticky="nsew", pady=PADY)
|
||||||
self.draw_spacer()
|
self.draw_spacer()
|
||||||
|
@ -98,9 +102,9 @@ class EmaneModelDialog(Dialog):
|
||||||
frame.grid(sticky="ew")
|
frame.grid(sticky="ew")
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
frame.columnconfigure(i, weight=1)
|
frame.columnconfigure(i, weight=1)
|
||||||
button = ttk.Button(frame, text="Apply", command=self.click_apply)
|
state = tk.NORMAL if self.enabled else tk.DISABLED
|
||||||
|
button = ttk.Button(frame, text="Apply", command=self.click_apply, state=state)
|
||||||
button.grid(row=0, column=0, sticky="ew", padx=PADX)
|
button.grid(row=0, column=0, sticky="ew", padx=PADX)
|
||||||
|
|
||||||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
button.grid(row=0, column=1, sticky="ew")
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
@ -124,6 +128,7 @@ class EmaneConfigDialog(Dialog):
|
||||||
model = self.node.emane.split("_")[1]
|
model = self.node.emane.split("_")[1]
|
||||||
self.emane_model: tk.StringVar = tk.StringVar(value=model)
|
self.emane_model: tk.StringVar = tk.StringVar(value=model)
|
||||||
self.emane_model_button: Optional[ttk.Button] = None
|
self.emane_model_button: Optional[ttk.Button] = None
|
||||||
|
self.enabled: bool = not self.app.core.is_runtime()
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self) -> None:
|
def draw(self) -> None:
|
||||||
|
@ -140,8 +145,9 @@ class EmaneConfigDialog(Dialog):
|
||||||
"""
|
"""
|
||||||
label = ttk.Label(
|
label = ttk.Label(
|
||||||
self.top,
|
self.top,
|
||||||
text="The EMANE emulation system provides more complex wireless radio emulation "
|
text="The EMANE emulation system provides more complex wireless radio "
|
||||||
"\nusing pluggable MAC and PHY modules. Refer to the wiki for configuration option details",
|
"emulation \nusing pluggable MAC and PHY modules. Refer to the wiki "
|
||||||
|
"for configuration option details",
|
||||||
justify=tk.CENTER,
|
justify=tk.CENTER,
|
||||||
)
|
)
|
||||||
label.grid(pady=PADY)
|
label.grid(pady=PADY)
|
||||||
|
@ -171,11 +177,9 @@ class EmaneConfigDialog(Dialog):
|
||||||
label.grid(row=0, column=0, sticky="w")
|
label.grid(row=0, column=0, sticky="w")
|
||||||
|
|
||||||
# create combo box and its binding
|
# create combo box and its binding
|
||||||
|
state = "readonly" if self.enabled else tk.DISABLED
|
||||||
combobox = ttk.Combobox(
|
combobox = ttk.Combobox(
|
||||||
frame,
|
frame, textvariable=self.emane_model, values=self.emane_models, state=state
|
||||||
textvariable=self.emane_model,
|
|
||||||
values=self.emane_models,
|
|
||||||
state="readonly",
|
|
||||||
)
|
)
|
||||||
combobox.grid(row=0, column=1, sticky="ew")
|
combobox.grid(row=0, column=1, sticky="ew")
|
||||||
combobox.bind("<<ComboboxSelected>>", self.emane_model_change)
|
combobox.bind("<<ComboboxSelected>>", self.emane_model_change)
|
||||||
|
@ -213,10 +217,9 @@ class EmaneConfigDialog(Dialog):
|
||||||
frame.grid(sticky="ew")
|
frame.grid(sticky="ew")
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
frame.columnconfigure(i, weight=1)
|
frame.columnconfigure(i, weight=1)
|
||||||
|
state = tk.NORMAL if self.enabled else tk.DISABLED
|
||||||
button = ttk.Button(frame, text="Apply", command=self.click_apply)
|
button = ttk.Button(frame, text="Apply", command=self.click_apply, state=state)
|
||||||
button.grid(row=0, column=0, padx=PADX, sticky="ew")
|
button.grid(row=0, column=0, padx=PADX, sticky="ew")
|
||||||
|
|
||||||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
button.grid(row=0, column=1, sticky="ew")
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,10 @@ class CanvasNode:
|
||||||
is_emane = self.core_node.type == NodeType.EMANE
|
is_emane = self.core_node.type == NodeType.EMANE
|
||||||
if self.app.core.is_runtime():
|
if self.app.core.is_runtime():
|
||||||
self.context.add_command(label="Configure", command=self.show_config)
|
self.context.add_command(label="Configure", command=self.show_config)
|
||||||
|
if is_emane:
|
||||||
|
self.context.add_command(
|
||||||
|
label="EMANE Config", command=self.show_emane_config
|
||||||
|
)
|
||||||
if is_wlan:
|
if is_wlan:
|
||||||
self.context.add_command(
|
self.context.add_command(
|
||||||
label="WLAN Config", command=self.show_wlan_config
|
label="WLAN Config", command=self.show_wlan_config
|
||||||
|
|
|
@ -85,12 +85,14 @@ class ConfigFrame(ttk.Notebook):
|
||||||
master: tk.Widget,
|
master: tk.Widget,
|
||||||
app: "Application",
|
app: "Application",
|
||||||
config: Dict[str, ConfigOption],
|
config: Dict[str, ConfigOption],
|
||||||
|
enabled: bool = True,
|
||||||
**kw: Any
|
**kw: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(master, **kw)
|
super().__init__(master, **kw)
|
||||||
self.app: "Application" = app
|
self.app: "Application" = app
|
||||||
self.config: Dict[str, ConfigOption] = config
|
self.config: Dict[str, ConfigOption] = config
|
||||||
self.values: Dict[str, tk.StringVar] = {}
|
self.values: Dict[str, tk.StringVar] = {}
|
||||||
|
self.enabled: bool = enabled
|
||||||
|
|
||||||
def draw_config(self) -> None:
|
def draw_config(self) -> None:
|
||||||
group_mapping = {}
|
group_mapping = {}
|
||||||
|
@ -110,8 +112,9 @@ class ConfigFrame(ttk.Notebook):
|
||||||
value = tk.StringVar()
|
value = tk.StringVar()
|
||||||
if option.type == core_pb2.ConfigOptionType.BOOL:
|
if option.type == core_pb2.ConfigOptionType.BOOL:
|
||||||
select = ("On", "Off")
|
select = ("On", "Off")
|
||||||
|
state = "readonly" if self.enabled else tk.DISABLED
|
||||||
combobox = ttk.Combobox(
|
combobox = ttk.Combobox(
|
||||||
tab.frame, textvariable=value, values=select, state="readonly"
|
tab.frame, textvariable=value, values=select, state=state
|
||||||
)
|
)
|
||||||
combobox.grid(row=index, column=1, sticky="ew")
|
combobox.grid(row=index, column=1, sticky="ew")
|
||||||
if option.value == "1":
|
if option.value == "1":
|
||||||
|
@ -121,32 +124,41 @@ class ConfigFrame(ttk.Notebook):
|
||||||
elif option.select:
|
elif option.select:
|
||||||
value.set(option.value)
|
value.set(option.value)
|
||||||
select = tuple(option.select)
|
select = tuple(option.select)
|
||||||
|
state = "readonly" if self.enabled else tk.DISABLED
|
||||||
combobox = ttk.Combobox(
|
combobox = ttk.Combobox(
|
||||||
tab.frame, textvariable=value, values=select, state="readonly"
|
tab.frame, textvariable=value, values=select, state=state
|
||||||
)
|
)
|
||||||
combobox.grid(row=index, column=1, sticky="ew")
|
combobox.grid(row=index, column=1, sticky="ew")
|
||||||
elif option.type == core_pb2.ConfigOptionType.STRING:
|
elif option.type == core_pb2.ConfigOptionType.STRING:
|
||||||
value.set(option.value)
|
value.set(option.value)
|
||||||
|
state = tk.NORMAL if self.enabled else tk.DISABLED
|
||||||
if "file" in option.label:
|
if "file" in option.label:
|
||||||
file_frame = ttk.Frame(tab.frame)
|
file_frame = ttk.Frame(tab.frame)
|
||||||
file_frame.grid(row=index, column=1, sticky="ew")
|
file_frame.grid(row=index, column=1, sticky="ew")
|
||||||
file_frame.columnconfigure(0, weight=1)
|
file_frame.columnconfigure(0, weight=1)
|
||||||
entry = ttk.Entry(file_frame, textvariable=value)
|
entry = ttk.Entry(file_frame, textvariable=value, state=state)
|
||||||
entry.grid(row=0, column=0, sticky="ew", padx=PADX)
|
entry.grid(row=0, column=0, sticky="ew", padx=PADX)
|
||||||
func = partial(file_button_click, value, self)
|
func = partial(file_button_click, value, self)
|
||||||
button = ttk.Button(file_frame, text="...", command=func)
|
button = ttk.Button(
|
||||||
|
file_frame, text="...", command=func, state=state
|
||||||
|
)
|
||||||
button.grid(row=0, column=1)
|
button.grid(row=0, column=1)
|
||||||
else:
|
else:
|
||||||
entry = ttk.Entry(tab.frame, textvariable=value)
|
entry = ttk.Entry(tab.frame, textvariable=value, state=state)
|
||||||
entry.grid(row=index, column=1, sticky="ew")
|
entry.grid(row=index, column=1, sticky="ew")
|
||||||
|
|
||||||
elif option.type in INT_TYPES:
|
elif option.type in INT_TYPES:
|
||||||
value.set(option.value)
|
value.set(option.value)
|
||||||
entry = validation.PositiveIntEntry(tab.frame, textvariable=value)
|
state = tk.NORMAL if self.enabled else tk.DISABLED
|
||||||
|
entry = validation.PositiveIntEntry(
|
||||||
|
tab.frame, textvariable=value, state=state
|
||||||
|
)
|
||||||
entry.grid(row=index, column=1, sticky="ew")
|
entry.grid(row=index, column=1, sticky="ew")
|
||||||
elif option.type == core_pb2.ConfigOptionType.FLOAT:
|
elif option.type == core_pb2.ConfigOptionType.FLOAT:
|
||||||
value.set(option.value)
|
value.set(option.value)
|
||||||
entry = validation.PositiveFloatEntry(tab.frame, textvariable=value)
|
state = tk.NORMAL if self.enabled else tk.DISABLED
|
||||||
|
entry = validation.PositiveFloatEntry(
|
||||||
|
tab.frame, textvariable=value, state=state
|
||||||
|
)
|
||||||
entry.grid(row=index, column=1, sticky="ew")
|
entry.grid(row=index, column=1, sticky="ew")
|
||||||
else:
|
else:
|
||||||
logging.error("unhandled config option type: %s", option.type)
|
logging.error("unhandled config option type: %s", option.type)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue