Merge branch 'coretk' into coretk-config
This commit is contained in:
commit
98cfb301bb
6 changed files with 183 additions and 186 deletions
|
@ -1,99 +0,0 @@
|
||||||
import enum
|
|
||||||
import logging
|
|
||||||
import tkinter as tk
|
|
||||||
from tkinter import ttk
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigType(enum.Enum):
|
|
||||||
STRING = 10
|
|
||||||
BOOL = 11
|
|
||||||
EMANECONFIG = 7
|
|
||||||
|
|
||||||
|
|
||||||
def create_config(master, config, padx=2, pady=2):
|
|
||||||
"""
|
|
||||||
Creates a scrollable canvas with an embedded window for displaying configuration
|
|
||||||
options. Will use grid layout to consume row 0 and columns 0-2.
|
|
||||||
|
|
||||||
:param master: master to add scrollable canvas to
|
|
||||||
:param dict config: config option mapping keys to config options
|
|
||||||
:param int padx: x padding for widgets
|
|
||||||
:param int pady: y padding for widgets
|
|
||||||
:return: widget value mapping
|
|
||||||
"""
|
|
||||||
master.rowconfigure(0, weight=1)
|
|
||||||
master.columnconfigure(0, weight=1)
|
|
||||||
master.columnconfigure(1, weight=1)
|
|
||||||
|
|
||||||
canvas = tk.Canvas(master, highlightthickness=0)
|
|
||||||
canvas.grid(row=0, columnspan=2, sticky="nsew", padx=padx, pady=pady)
|
|
||||||
canvas.columnconfigure(0, weight=1)
|
|
||||||
canvas.rowconfigure(0, weight=1)
|
|
||||||
|
|
||||||
scroll_y = tk.Scrollbar(master, orient="vertical", command=canvas.yview)
|
|
||||||
scroll_y.grid(row=0, column=2, sticky="ns")
|
|
||||||
|
|
||||||
frame = tk.Frame(canvas, padx=padx, pady=pady)
|
|
||||||
frame.columnconfigure(0, weight=1)
|
|
||||||
frame.columnconfigure(1, weight=3)
|
|
||||||
|
|
||||||
values = {}
|
|
||||||
for index, key in enumerate(sorted(config)):
|
|
||||||
option = config[key]
|
|
||||||
label = tk.Label(frame, text=option.label)
|
|
||||||
label.grid(row=index, pady=pady, padx=padx, sticky="ew")
|
|
||||||
value = tk.StringVar()
|
|
||||||
config_type = ConfigType(option.type)
|
|
||||||
if config_type == ConfigType.BOOL:
|
|
||||||
select = tuple(option.select)
|
|
||||||
combobox = ttk.Combobox(frame, textvariable=value, values=select)
|
|
||||||
combobox.grid(row=index, column=1, sticky="ew", pady=pady)
|
|
||||||
if option.value == "1":
|
|
||||||
value.set("On")
|
|
||||||
else:
|
|
||||||
value.set("Off")
|
|
||||||
elif config_type == ConfigType.STRING:
|
|
||||||
value.set(option.value)
|
|
||||||
entry = tk.Entry(frame, textvariable=value)
|
|
||||||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
|
||||||
elif config_type == ConfigType.EMANECONFIG:
|
|
||||||
value.set(option.value)
|
|
||||||
entry = tk.Entry(frame, textvariable=value, bg="white")
|
|
||||||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
|
||||||
else:
|
|
||||||
logging.error("unhandled config option type: %s", config_type)
|
|
||||||
values[key] = value
|
|
||||||
|
|
||||||
frame_id = canvas.create_window(0, 0, anchor="nw", window=frame)
|
|
||||||
canvas.update_idletasks()
|
|
||||||
canvas.configure(scrollregion=canvas.bbox("all"), yscrollcommand=scroll_y.set)
|
|
||||||
|
|
||||||
frame.bind(
|
|
||||||
"<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all"))
|
|
||||||
)
|
|
||||||
canvas.bind(
|
|
||||||
"<Configure>", lambda event: canvas.itemconfig(frame_id, width=event.width)
|
|
||||||
)
|
|
||||||
return values
|
|
||||||
|
|
||||||
|
|
||||||
def parse_config(options, values):
|
|
||||||
"""
|
|
||||||
Given a set of configurations, parse out values and transform them when needed.
|
|
||||||
|
|
||||||
:param dict options: option key mapping to configuration options
|
|
||||||
:param dict values: option key mapping to widget values
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
for key in options:
|
|
||||||
option = options[key]
|
|
||||||
value = values[key]
|
|
||||||
config_type = ConfigType(option.type)
|
|
||||||
config_value = value.get()
|
|
||||||
if config_type == ConfigType.BOOL:
|
|
||||||
if config_value == "On":
|
|
||||||
option.value = "1"
|
|
||||||
else:
|
|
||||||
option.value = "0"
|
|
||||||
else:
|
|
||||||
option.value = config_value
|
|
|
@ -28,6 +28,7 @@ class ServicesSelectDialog(Dialog):
|
||||||
for group in sorted(self.app.core.services):
|
for group in sorted(self.app.core.services):
|
||||||
self.groups.listbox.insert(tk.END, group)
|
self.groups.listbox.insert(tk.END, group)
|
||||||
self.groups.listbox.bind("<<ListboxSelect>>", self.handle_group_change)
|
self.groups.listbox.bind("<<ListboxSelect>>", self.handle_group_change)
|
||||||
|
self.groups.listbox.selection_set(0)
|
||||||
|
|
||||||
self.services = CheckboxList(
|
self.services = CheckboxList(
|
||||||
frame, text="Services", clicked=self.service_clicked
|
frame, text="Services", clicked=self.service_clicked
|
||||||
|
@ -46,6 +47,9 @@ class ServicesSelectDialog(Dialog):
|
||||||
button = tk.Button(frame, text="Cancel", command=self.destroy)
|
button = tk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
button.grid(row=0, column=1, sticky="ew")
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
# trigger group change
|
||||||
|
self.groups.listbox.event_generate("<<ListboxSelect>>")
|
||||||
|
|
||||||
def handle_group_change(self, event):
|
def handle_group_change(self, event):
|
||||||
selection = self.groups.listbox.curselection()
|
selection = self.groups.listbox.curselection()
|
||||||
if selection:
|
if selection:
|
||||||
|
@ -53,7 +57,8 @@ class ServicesSelectDialog(Dialog):
|
||||||
group = self.groups.listbox.get(index)
|
group = self.groups.listbox.get(index)
|
||||||
self.services.clear()
|
self.services.clear()
|
||||||
for service in sorted(self.app.core.services[group], key=lambda x: x.name):
|
for service in sorted(self.app.core.services[group], key=lambda x: x.name):
|
||||||
self.services.add(service.name)
|
checked = service.name in self.current_services
|
||||||
|
self.services.add(service.name, checked)
|
||||||
|
|
||||||
def service_clicked(self, name, var):
|
def service_clicked(self, name, var):
|
||||||
if var.get() and name not in self.current_services:
|
if var.get() and name not in self.current_services:
|
||||||
|
|
|
@ -7,9 +7,9 @@ import tkinter as tk
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
|
|
||||||
from coretk import configutils
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
|
from coretk.widgets import ConfigFrame
|
||||||
|
|
||||||
PAD_X = 2
|
PAD_X = 2
|
||||||
PAD_Y = 2
|
PAD_Y = 2
|
||||||
|
@ -38,10 +38,10 @@ class EmaneConfiguration(Dialog):
|
||||||
self.emane_options()
|
self.emane_options()
|
||||||
self.draw_apply_and_cancel()
|
self.draw_apply_and_cancel()
|
||||||
|
|
||||||
self.values = None
|
self.emane_config_frame = None
|
||||||
self.options = app.core.emane_config
|
self.options = app.core.emane_config
|
||||||
self.model_options = None
|
self.model_options = None
|
||||||
self.model_values = None
|
self.model_config_frame = None
|
||||||
|
|
||||||
def create_text_variable(self, val):
|
def create_text_variable(self, val):
|
||||||
"""
|
"""
|
||||||
|
@ -75,7 +75,7 @@ class EmaneConfiguration(Dialog):
|
||||||
f.grid(row=0, column=0, sticky="nsew")
|
f.grid(row=0, column=0, sticky="nsew")
|
||||||
|
|
||||||
def save_emane_option(self):
|
def save_emane_option(self):
|
||||||
configutils.parse_config(self.options, self.values)
|
self.emane_config_frame.parse_config()
|
||||||
self.emane_dialog.destroy()
|
self.emane_dialog.destroy()
|
||||||
|
|
||||||
def draw_emane_options(self):
|
def draw_emane_options(self):
|
||||||
|
@ -83,21 +83,27 @@ class EmaneConfiguration(Dialog):
|
||||||
self.emane_dialog = Dialog(
|
self.emane_dialog = Dialog(
|
||||||
self, self.app, "emane configuration", modal=False
|
self, self.app, "emane configuration", modal=False
|
||||||
)
|
)
|
||||||
b1 = tk.Button(self.emane_dialog, text="Appy", command=self.save_emane_option)
|
|
||||||
b2 = tk.Button(
|
|
||||||
self.emane_dialog, text="Cancel", command=self.emane_dialog.destroy
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.options is None:
|
if self.options is None:
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
response = self.app.core.client.get_emane_config(session_id)
|
response = self.app.core.client.get_emane_config(session_id)
|
||||||
logging.info("emane config: %s", response)
|
logging.info("emane config: %s", response)
|
||||||
self.options = response.config
|
self.options = response.config
|
||||||
self.values = configutils.create_config(
|
|
||||||
self.emane_dialog, self.options, PAD_X, PAD_Y
|
self.emane_dialog.columnconfigure(0, weight=1)
|
||||||
)
|
self.emane_dialog.rowconfigure(0, weight=1)
|
||||||
b1.grid(row=1, column=0)
|
self.emane_config_frame = ConfigFrame(self.emane_dialog, config=self.options)
|
||||||
b2.grid(row=1, column=1)
|
self.emane_config_frame.draw_config()
|
||||||
|
self.emane_config_frame.grid(sticky="nsew")
|
||||||
|
|
||||||
|
frame = tk.Frame(self.emane_dialog)
|
||||||
|
frame.grid(sticky="ew")
|
||||||
|
for i in range(2):
|
||||||
|
frame.columnconfigure(i, weight=1)
|
||||||
|
b1 = tk.Button(frame, text="Appy", command=self.save_emane_option)
|
||||||
|
b1.grid(row=0, column=0, sticky="ew")
|
||||||
|
b2 = tk.Button(frame, text="Cancel", command=self.emane_dialog.destroy)
|
||||||
|
b2.grid(row=0, column=1, sticky="ew")
|
||||||
self.emane_dialog.show()
|
self.emane_dialog.show()
|
||||||
|
|
||||||
def save_emane_model_options(self):
|
def save_emane_model_options(self):
|
||||||
|
@ -110,8 +116,7 @@ class EmaneConfiguration(Dialog):
|
||||||
model_name = self.emane_models[self.emane_model_combobox.current()]
|
model_name = self.emane_models[self.emane_model_combobox.current()]
|
||||||
|
|
||||||
# parse configuration
|
# parse configuration
|
||||||
configutils.parse_config(self.model_options, self.model_values)
|
config = self.model_config_frame.parse_config()
|
||||||
config = {x: self.model_options[x].value for x in self.model_options}
|
|
||||||
|
|
||||||
# add string emane_ infront for grpc call
|
# add string emane_ infront for grpc call
|
||||||
response = self.app.core.client.set_emane_model_config(
|
response = self.app.core.client.set_emane_model_config(
|
||||||
|
@ -145,17 +150,10 @@ class EmaneConfiguration(Dialog):
|
||||||
# create the dialog and the necessry widget
|
# create the dialog and the necessry widget
|
||||||
if not self.emane_model_dialog or not self.emane_model_dialog.winfo_exists():
|
if not self.emane_model_dialog or not self.emane_model_dialog.winfo_exists():
|
||||||
self.emane_model_dialog = Dialog(
|
self.emane_model_dialog = Dialog(
|
||||||
self, self.app, model_name + " configuration", modal=False
|
self, self.app, f"{model_name} configuration", modal=False
|
||||||
)
|
)
|
||||||
|
self.emane_model_dialog.columnconfigure(0, weight=1)
|
||||||
b1 = tk.Button(
|
self.emane_model_dialog.rowconfigure(0, weight=1)
|
||||||
self.emane_model_dialog, text="Apply", command=self.save_emane_model_options
|
|
||||||
)
|
|
||||||
b2 = tk.Button(
|
|
||||||
self.emane_model_dialog,
|
|
||||||
text="Cancel",
|
|
||||||
command=self.emane_model_dialog.destroy,
|
|
||||||
)
|
|
||||||
|
|
||||||
# query for configurations
|
# query for configurations
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
|
@ -166,12 +164,20 @@ class EmaneConfiguration(Dialog):
|
||||||
logging.info("emane model config %s", response)
|
logging.info("emane model config %s", response)
|
||||||
|
|
||||||
self.model_options = response.config
|
self.model_options = response.config
|
||||||
self.model_values = configutils.create_config(
|
self.model_config_frame = ConfigFrame(
|
||||||
self.emane_model_dialog, self.model_options, PAD_X, PAD_Y
|
self.emane_model_dialog, config=self.model_options
|
||||||
)
|
)
|
||||||
|
self.model_config_frame.grid(sticky="nsew")
|
||||||
|
self.model_config_frame.draw_config()
|
||||||
|
|
||||||
b1.grid(row=1, column=0, sticky="nsew")
|
frame = tk.Frame(self.emane_model_dialog)
|
||||||
b2.grid(row=1, column=1, sticky="nsew")
|
frame.grid(sticky="ew")
|
||||||
|
for i in range(2):
|
||||||
|
frame.columnconfigure(i, weight=1)
|
||||||
|
b1 = tk.Button(frame, text="Apply", command=self.save_emane_model_options)
|
||||||
|
b1.grid(row=0, column=0, sticky="ew")
|
||||||
|
b2 = tk.Button(frame, text="Cancel", command=self.emane_model_dialog.destroy)
|
||||||
|
b2.grid(row=0, column=1, sticky="ew")
|
||||||
self.emane_model_dialog.show()
|
self.emane_model_dialog.show()
|
||||||
|
|
||||||
def draw_option_buttons(self, parent):
|
def draw_option_buttons(self, parent):
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import logging
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
|
||||||
from coretk import configutils
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.widgets import ConfigFrame
|
||||||
|
|
||||||
PAD_X = 2
|
PAD_X = 2
|
||||||
PAD_Y = 2
|
PAD_Y = 2
|
||||||
|
@ -11,25 +11,33 @@ PAD_Y = 2
|
||||||
class SessionOptionsDialog(Dialog):
|
class SessionOptionsDialog(Dialog):
|
||||||
def __init__(self, master, app):
|
def __init__(self, master, app):
|
||||||
super().__init__(master, app, "Session Options", modal=True)
|
super().__init__(master, app, "Session Options", modal=True)
|
||||||
self.options = None
|
self.config_frame = None
|
||||||
self.values = None
|
|
||||||
self.save_button = tk.Button(self, text="Save", command=self.save)
|
|
||||||
self.cancel_button = tk.Button(self, text="Cancel", command=self.destroy)
|
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
self.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
response = self.app.core.client.get_session_options(session_id)
|
response = self.app.core.client.get_session_options(session_id)
|
||||||
logging.info("session options: %s", response)
|
logging.info("session options: %s", response)
|
||||||
self.options = response.config
|
|
||||||
self.values = configutils.create_config(self, self.options, PAD_X, PAD_Y)
|
self.config_frame = ConfigFrame(self, config=response.config)
|
||||||
self.save_button.grid(row=1, pady=PAD_Y, padx=PAD_X, sticky="ew")
|
self.config_frame.draw_config()
|
||||||
self.cancel_button.grid(row=1, column=1, pady=PAD_Y, padx=PAD_X, sticky="ew")
|
self.config_frame.grid(sticky="nsew")
|
||||||
|
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(sticky="ew")
|
||||||
|
for i in range(2):
|
||||||
|
frame.columnconfigure(i, weight=1)
|
||||||
|
button = tk.Button(frame, text="Save", command=self.save)
|
||||||
|
button.grid(row=0, column=0, pady=PAD_Y, padx=PAD_X, sticky="ew")
|
||||||
|
button = tk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
|
button.grid(row=0, column=1, pady=PAD_Y, padx=PAD_X, sticky="ew")
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
configutils.parse_config(self.options, self.values)
|
config = self.config_frame.parse_config()
|
||||||
session_id = self.app.core.session_id
|
session_id = self.app.core.session_id
|
||||||
config = {x: self.options[x].value for x in self.options}
|
|
||||||
response = self.app.core.client.set_session_options(session_id, config)
|
response = self.app.core.client.set_session_options(session_id, config)
|
||||||
logging.info("saved session config: %s", response)
|
logging.info("saved session config: %s", response)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
|
@ -1,42 +1,131 @@
|
||||||
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from tkinter import ttk
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
|
|
||||||
|
INT_TYPES = {
|
||||||
|
core_pb2.ConfigOptionType.UINT8,
|
||||||
|
core_pb2.ConfigOptionType.UINT16,
|
||||||
|
core_pb2.ConfigOptionType.UINT32,
|
||||||
|
core_pb2.ConfigOptionType.UINT64,
|
||||||
|
core_pb2.ConfigOptionType.INT8,
|
||||||
|
core_pb2.ConfigOptionType.INT16,
|
||||||
|
core_pb2.ConfigOptionType.INT32,
|
||||||
|
core_pb2.ConfigOptionType.INT64,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class FrameScroll(tk.LabelFrame):
|
class FrameScroll(tk.LabelFrame):
|
||||||
def __init__(self, master=None, cnf={}, **kw):
|
def __init__(self, master=None, cnf={}, _cls=tk.Frame, **kw):
|
||||||
super().__init__(master, cnf, **kw)
|
super().__init__(master, cnf, **kw)
|
||||||
self.rowconfigure(0, weight=1)
|
self.rowconfigure(0, weight=1)
|
||||||
self.columnconfigure(0, weight=1)
|
self.columnconfigure(0, weight=1)
|
||||||
self.columnconfigure(1, weight=1)
|
|
||||||
self.canvas = tk.Canvas(self, highlightthickness=0)
|
self.canvas = tk.Canvas(self, highlightthickness=0)
|
||||||
self.canvas.grid(row=0, columnspan=2, sticky="nsew", padx=2, pady=2)
|
self.canvas.grid(row=0, sticky="nsew", padx=2, pady=2)
|
||||||
self.canvas.columnconfigure(0, weight=1)
|
self.canvas.columnconfigure(0, weight=1)
|
||||||
self.canvas.rowconfigure(0, weight=1)
|
self.canvas.rowconfigure(0, weight=1)
|
||||||
self.scrollbar = tk.Scrollbar(
|
self.scrollbar = tk.Scrollbar(
|
||||||
self, orient="vertical", command=self.canvas.yview
|
self, orient="vertical", command=self.canvas.yview
|
||||||
)
|
)
|
||||||
self.scrollbar.grid(row=0, column=2, sticky="ns")
|
self.scrollbar.grid(row=0, column=1, sticky="ns")
|
||||||
self.frame = tk.Frame(self.canvas, padx=2, pady=2)
|
self.frame = _cls(self.canvas)
|
||||||
self.frame.columnconfigure(0, weight=1)
|
|
||||||
self.frame_id = self.canvas.create_window(0, 0, anchor="nw", window=self.frame)
|
self.frame_id = self.canvas.create_window(0, 0, anchor="nw", window=self.frame)
|
||||||
self.canvas.update_idletasks()
|
self.canvas.update_idletasks()
|
||||||
self.canvas.configure(
|
self.canvas.configure(
|
||||||
scrollregion=self.canvas.bbox("all"), yscrollcommand=self.scrollbar.set
|
scrollregion=self.canvas.bbox("all"), yscrollcommand=self.scrollbar.set
|
||||||
)
|
)
|
||||||
self.frame.bind(
|
self.frame.bind("<Configure>", self._configure_frame)
|
||||||
"<Configure>",
|
self.canvas.bind("<Configure>", self._configure_canvas)
|
||||||
lambda event: self.canvas.configure(scrollregion=self.canvas.bbox("all")),
|
|
||||||
)
|
def _configure_frame(self, event):
|
||||||
self.canvas.bind(
|
req_width = self.frame.winfo_reqwidth()
|
||||||
"<Configure>",
|
if req_width != self.canvas.winfo_reqwidth():
|
||||||
lambda event: self.canvas.itemconfig(self.frame_id, width=event.width),
|
self.canvas.configure(width=req_width)
|
||||||
)
|
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
||||||
|
|
||||||
|
def _configure_canvas(self, event):
|
||||||
|
self.canvas.itemconfig(self.frame_id, width=event.width)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
for widget in self.frame.winfo_children():
|
for widget in self.frame.winfo_children():
|
||||||
widget.destroy()
|
widget.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFrame(FrameScroll):
|
||||||
|
def __init__(self, master=None, cnf={}, config=None, **kw):
|
||||||
|
super().__init__(master, cnf, ttk.Notebook, **kw)
|
||||||
|
self.config = config
|
||||||
|
self.values = {}
|
||||||
|
|
||||||
|
def draw_config(self):
|
||||||
|
padx = 2
|
||||||
|
pady = 2
|
||||||
|
group_mapping = {}
|
||||||
|
for key in self.config:
|
||||||
|
option = self.config[key]
|
||||||
|
group = group_mapping.setdefault(option.group, [])
|
||||||
|
group.append(option)
|
||||||
|
|
||||||
|
for group_name in sorted(group_mapping):
|
||||||
|
group = group_mapping[group_name]
|
||||||
|
frame = tk.Frame(self.frame)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
self.frame.add(frame, text=group_name)
|
||||||
|
for index, option in enumerate(sorted(group, key=lambda x: x.name)):
|
||||||
|
label = tk.Label(frame, text=option.label)
|
||||||
|
label.grid(row=index, pady=pady, padx=padx, sticky="w")
|
||||||
|
value = tk.StringVar()
|
||||||
|
if option.type == core_pb2.ConfigOptionType.BOOL:
|
||||||
|
select = tuple(option.select)
|
||||||
|
combobox = ttk.Combobox(
|
||||||
|
frame, textvariable=value, values=select, state="readonly"
|
||||||
|
)
|
||||||
|
combobox.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
if option.value == "1":
|
||||||
|
value.set("On")
|
||||||
|
else:
|
||||||
|
value.set("Off")
|
||||||
|
elif option.select:
|
||||||
|
value.set(option.value)
|
||||||
|
select = tuple(option.select)
|
||||||
|
combobox = ttk.Combobox(
|
||||||
|
frame, textvariable=value, values=select, state="readonly"
|
||||||
|
)
|
||||||
|
combobox.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
elif option.type == core_pb2.ConfigOptionType.STRING:
|
||||||
|
value.set(option.value)
|
||||||
|
entry = tk.Entry(frame, textvariable=value)
|
||||||
|
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
elif option.type in INT_TYPES:
|
||||||
|
value.set(option.value)
|
||||||
|
entry = tk.Entry(frame, textvariable=value)
|
||||||
|
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
elif option.type == core_pb2.ConfigOptionType.FLOAT:
|
||||||
|
value.set(option.value)
|
||||||
|
entry = tk.Entry(frame, textvariable=value)
|
||||||
|
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
else:
|
||||||
|
logging.error("unhandled config option type: %s", option.type)
|
||||||
|
self.values[option.name] = value
|
||||||
|
|
||||||
|
def parse_config(self):
|
||||||
|
for key in self.config:
|
||||||
|
option = self.config[key]
|
||||||
|
value = self.values[key]
|
||||||
|
config_value = value.get()
|
||||||
|
if option.type == core_pb2.ConfigOptionType.BOOL:
|
||||||
|
if config_value == "On":
|
||||||
|
option.value = "1"
|
||||||
|
else:
|
||||||
|
option.value = "0"
|
||||||
|
else:
|
||||||
|
option.value = config_value
|
||||||
|
|
||||||
|
return {x: self.config[x].value for x in self.config}
|
||||||
|
|
||||||
|
|
||||||
class ListboxScroll(tk.LabelFrame):
|
class ListboxScroll(tk.LabelFrame):
|
||||||
def __init__(self, master=None, cnf={}, **kw):
|
def __init__(self, master=None, cnf={}, **kw):
|
||||||
super().__init__(master, cnf, **kw)
|
super().__init__(master, cnf, **kw)
|
||||||
|
@ -51,43 +140,14 @@ class ListboxScroll(tk.LabelFrame):
|
||||||
self.scrollbar.config(command=self.listbox.yview)
|
self.scrollbar.config(command=self.listbox.yview)
|
||||||
|
|
||||||
|
|
||||||
class CheckboxList(tk.LabelFrame):
|
class CheckboxList(FrameScroll):
|
||||||
def __init__(self, master=None, cnf={}, clicked=None, **kw):
|
def __init__(self, master=None, cnf={}, clicked=None, **kw):
|
||||||
super().__init__(master, cnf, **kw)
|
super().__init__(master, cnf, **kw)
|
||||||
self.clicked = clicked
|
self.clicked = clicked
|
||||||
self.rowconfigure(0, weight=1)
|
|
||||||
self.columnconfigure(0, weight=1)
|
|
||||||
self.columnconfigure(1, weight=1)
|
|
||||||
self.canvas = tk.Canvas(self, highlightthickness=0)
|
|
||||||
self.canvas.grid(row=0, columnspan=2, sticky="nsew", padx=2, pady=2)
|
|
||||||
self.canvas.columnconfigure(0, weight=1)
|
|
||||||
self.canvas.rowconfigure(0, weight=1)
|
|
||||||
self.scrollbar = tk.Scrollbar(
|
|
||||||
self, orient="vertical", command=self.canvas.yview
|
|
||||||
)
|
|
||||||
self.scrollbar.grid(row=0, column=2, sticky="ns")
|
|
||||||
self.frame = tk.Frame(self.canvas, padx=2, pady=2)
|
|
||||||
self.frame.columnconfigure(0, weight=1)
|
self.frame.columnconfigure(0, weight=1)
|
||||||
self.frame_id = self.canvas.create_window(0, 0, anchor="nw", window=self.frame)
|
|
||||||
self.canvas.update_idletasks()
|
|
||||||
self.canvas.configure(
|
|
||||||
scrollregion=self.canvas.bbox("all"), yscrollcommand=self.scrollbar.set
|
|
||||||
)
|
|
||||||
self.frame.bind(
|
|
||||||
"<Configure>",
|
|
||||||
lambda event: self.canvas.configure(scrollregion=self.canvas.bbox("all")),
|
|
||||||
)
|
|
||||||
self.canvas.bind(
|
|
||||||
"<Configure>",
|
|
||||||
lambda event: self.canvas.itemconfig(self.frame_id, width=event.width),
|
|
||||||
)
|
|
||||||
|
|
||||||
def clear(self):
|
def add(self, name, checked):
|
||||||
for widget in self.frame.winfo_children():
|
var = tk.BooleanVar(value=checked)
|
||||||
widget.destroy()
|
|
||||||
|
|
||||||
def add(self, name):
|
|
||||||
var = tk.BooleanVar()
|
|
||||||
func = partial(self.clicked, name, var)
|
func = partial(self.clicked, name, var)
|
||||||
checkbox = tk.Checkbutton(self.frame, text=name, variable=var, command=func)
|
checkbox = tk.Checkbutton(self.frame, text=name, variable=var, command=func)
|
||||||
checkbox.grid(sticky="w")
|
checkbox.grid(sticky="w")
|
||||||
|
|
|
@ -768,6 +768,23 @@ message NodeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ConfigOptionType {
|
||||||
|
enum Enum {
|
||||||
|
NONE = 0;
|
||||||
|
UINT8 = 1;
|
||||||
|
UINT16 = 2;
|
||||||
|
UINT32 = 3;
|
||||||
|
UINT64 = 4;
|
||||||
|
INT8 = 5;
|
||||||
|
INT16 = 6;
|
||||||
|
INT32 = 7;
|
||||||
|
INT64 = 8;
|
||||||
|
FLOAT = 9;
|
||||||
|
STRING = 10;
|
||||||
|
BOOL = 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message ServiceValidationMode {
|
message ServiceValidationMode {
|
||||||
enum Enum {
|
enum Enum {
|
||||||
BLOCKING = 0;
|
BLOCKING = 0;
|
||||||
|
|
Loading…
Reference in a new issue