示例#1
0
 def draw(self) -> None:
     self.top.columnconfigure(0, weight=1)
     self.top.rowconfigure(0, weight=1)
     self.config_frame = ConfigFrame(self.top, self.app, self.config, self.enabled)
     self.config_frame.draw_config()
     self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
     self.draw_buttons()
示例#2
0
 def draw(self):
     self.top.columnconfigure(0, weight=1)
     self.top.rowconfigure(0, weight=1)
     self.config_frame = ConfigFrame(self.top, self.app, self.config)
     self.config_frame.draw_config()
     self.config_frame.grid(sticky="nsew", pady=PADY)
     self.draw_apply_buttons()
示例#3
0
class SessionOptionsDialog(Dialog):
    def __init__(self, app: "Application") -> None:
        super().__init__(app, "Session Options")
        self.config_frame: Optional[ConfigFrame] = None
        self.has_error: bool = False
        self.enabled: bool = not self.app.core.is_runtime()
        if not self.has_error:
            self.draw()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        options = self.app.core.session.options
        self.config_frame = ConfigFrame(self.top, self.app, options,
                                        self.enabled)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)

        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        state = tk.NORMAL if self.enabled else tk.DISABLED
        button = ttk.Button(frame, text="Save", command=self.save, state=state)
        button.grid(row=0, column=0, padx=PADX, sticky=tk.EW)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def save(self) -> None:
        config = self.config_frame.parse_config()
        for key, value in config.items():
            self.app.core.session.options[key].value = value
        self.destroy()
示例#4
0
 def draw(self) -> None:
     self.top.columnconfigure(0, weight=1)
     self.top.rowconfigure(0, weight=1)
     self.config_frame = ConfigFrame(self.top, self.app, self.config)
     self.config_frame.draw_config()
     self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
     self.draw_apply_buttons()
     self.top.bind("<Destroy>", self.remove_ranges)
示例#5
0
 def draw(self) -> None:
     self.top.columnconfigure(0, weight=1)
     self.top.rowconfigure(0, weight=1)
     self.config_frame = ConfigFrame(self.top, self.app,
                                     self.app.core.emane_config,
                                     self.enabled)
     self.config_frame.draw_config()
     self.config_frame.grid(sticky="nsew", pady=PADY)
     self.draw_spacer()
     self.draw_buttons()
示例#6
0
class WlanConfigDialog(Dialog):
    def __init__(self, master, app, canvas_node):
        super().__init__(master,
                         app,
                         f"{canvas_node.core_node.name} Wlan Configuration",
                         modal=True)
        self.canvas_node = canvas_node
        self.node = canvas_node.core_node
        self.config_frame = None
        try:
            self.config = self.app.core.get_wlan_config(self.node.id)
        except grpc.RpcError as e:
            show_grpc_error(e)
            self.destroy()
        self.draw()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)
        self.draw_apply_buttons()

    def draw_apply_buttons(self):
        """
        create node configuration options

        :return: nothing
        """
        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)

        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, padx=PADX, sticky="ew")

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky="ew")

    def click_apply(self):
        """
        retrieve user's wlan configuration and store the new configuration values

        :return: nothing
        """
        config = self.config_frame.parse_config()
        self.app.core.wlan_configs[self.node.id] = self.config
        if self.app.core.is_runtime():
            session_id = self.app.core.session_id
            self.app.core.client.set_wlan_config(session_id, self.node.id,
                                                 config)
        self.destroy()
示例#7
0
class SessionOptionsDialog(Dialog):
    def __init__(self, app: "Application") -> None:
        super().__init__(app, "Session Options")
        self.config_frame: Optional[ConfigFrame] = None
        self.has_error: bool = False
        self.config: Dict[str, ConfigOption] = self.get_config()
        self.enabled: bool = not self.app.core.is_runtime()
        if not self.has_error:
            self.draw()

    def get_config(self) -> Dict[str, ConfigOption]:
        try:
            session_id = self.app.core.session.id
            response = self.app.core.client.get_session_options(session_id)
            return ConfigOption.from_dict(response.config)
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Get Session Options Error", e)
            self.has_error = True
            self.destroy()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config,
                                        self.enabled)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)

        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        state = tk.NORMAL if self.enabled else tk.DISABLED
        button = ttk.Button(frame, text="Save", command=self.save, state=state)
        button.grid(row=0, column=0, padx=PADX, sticky=tk.EW)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def save(self) -> None:
        config = self.config_frame.parse_config()
        try:
            session_id = self.app.core.session.id
            response = self.app.core.client.set_session_options(
                session_id, config)
            logging.info("saved session config: %s", response)
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Set Session Options Error", e)
        self.destroy()
示例#8
0
    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        self.config_frame = ConfigFrame(self.top, self.app, config=self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)

        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Save", command=self.save)
        button.grid(row=0, column=0, padx=PADX, sticky="ew")
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky="ew")
示例#9
0
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()
        if not self.has_error:
            self.draw()

    def get_config(self):
        try:
            session_id = self.app.core.session_id
            response = self.app.core.client.get_session_options(session_id)
            return response.config
        except grpc.RpcError as e:
            self.has_error = True
            show_grpc_error(e, self.app, self.app)
            self.destroy()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        self.config_frame = ConfigFrame(self.top, self.app, config=self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)

        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Save", command=self.save)
        button.grid(row=0, column=0, padx=PADX, sticky="ew")
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, padx=PADX, sticky="ew")

    def save(self):
        config = self.config_frame.parse_config()
        try:
            session_id = self.app.core.session_id
            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, self.top, self.app)
        self.destroy()
示例#10
0
    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config,
                                        self.enabled)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)

        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        state = tk.NORMAL if self.enabled else tk.DISABLED
        button = ttk.Button(frame, text="Save", command=self.save, state=state)
        button.grid(row=0, column=0, padx=PADX, sticky=tk.EW)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)
示例#11
0
class GlobalEmaneDialog(Dialog):
    def __init__(self, master: tk.BaseWidget, app: "Application") -> None:
        super().__init__(app, "EMANE Configuration", master=master)
        self.config_frame: Optional[ConfigFrame] = None
        self.enabled: bool = not self.app.core.is_runtime()
        self.draw()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        session = self.app.core.session
        self.config_frame = ConfigFrame(self.top, self.app,
                                        session.emane_config, self.enabled)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
        self.draw_buttons()

    def draw_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        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=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def click_apply(self) -> None:
        self.config_frame.parse_config()
        self.destroy()
示例#12
0
class GlobalEmaneDialog(Dialog):
    def __init__(self, master, app):
        super().__init__(master, app, "EMANE Configuration", modal=True)
        self.config_frame = None
        self.draw()

    def draw(self):
        self.top.columnconfigure(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.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)
        self.draw_spacer()
        self.draw_buttons()

    def draw_buttons(self):
        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky="ew")

    def click_apply(self):
        self.config_frame.parse_config()
        self.destroy()
示例#13
0
class EmaneModelDialog(Dialog):
    def __init__(
        self,
        master: tk.BaseWidget,
        app: "Application",
        node: Node,
        model: str,
        iface_id: int = None,
    ) -> None:
        super().__init__(app,
                         f"{node.name} {model} Configuration",
                         master=master)
        self.node: Node = node
        self.model: str = f"emane_{model}"
        self.iface_id: int = iface_id
        self.config_frame: Optional[ConfigFrame] = None
        self.enabled: bool = not self.app.core.is_runtime()
        self.has_error: bool = False
        try:
            config = self.node.emane_model_configs.get(
                (self.model, self.iface_id))
            if not config:
                config = self.app.core.get_emane_model_config(
                    self.node.id, self.model, self.iface_id)
            self.config: Dict[str, ConfigOption] = config
            self.draw()
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Get EMANE Config Error", e)
            self.has_error: bool = True
            self.destroy()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config,
                                        self.enabled)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
        self.draw_buttons()

    def draw_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        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=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def click_apply(self) -> None:
        self.config_frame.parse_config()
        key = (self.model, self.iface_id)
        self.node.emane_model_configs[key] = self.config
        self.destroy()
示例#14
0
    def draw_tab_config(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Configuration")

        if self.modes:
            frame = ttk.Frame(tab)
            frame.grid(sticky=tk.EW, pady=PADY)
            frame.columnconfigure(1, weight=1)
            label = ttk.Label(frame, text="Modes")
            label.grid(row=0, column=0, padx=PADX)
            self.modes_combobox = ttk.Combobox(
                frame, values=self.modes, state="readonly"
            )
            self.modes_combobox.bind("<<ComboboxSelected>>", self.handle_mode_changed)
            self.modes_combobox.grid(row=0, column=1, sticky=tk.EW, pady=PADY)

        logger.info("config service config: %s", self.config)
        self.config_frame = ConfigFrame(tab, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
        tab.rowconfigure(self.config_frame.grid_info()["row"], weight=1)
示例#15
0
class EmaneModelDialog(Dialog):
    def __init__(
        self,
        master: Any,
        app: "Application",
        node: core_pb2.Node,
        model: str,
        interface: int = None,
    ):
        super().__init__(master,
                         app,
                         f"{node.name} {model} Configuration",
                         modal=True)
        self.node = node
        self.model = f"emane_{model}"
        self.interface = interface
        self.config_frame = None
        self.has_error = False
        try:
            self.config = self.app.core.get_emane_model_config(
                self.node.id, self.model, self.interface)
            self.draw()
        except grpc.RpcError as e:
            show_grpc_error(e, self.app, self.app)
            self.has_error = True
            self.destroy()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)
        self.draw_spacer()
        self.draw_buttons()

    def draw_buttons(self):
        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, sticky="ew", padx=PADX)

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky="ew")

    def click_apply(self):
        self.config_frame.parse_config()
        self.app.core.set_emane_model_config(self.node.id, self.model,
                                             self.config, self.interface)
        self.destroy()
示例#16
0
class MobilityConfigDialog(Dialog):
    def __init__(self, master: "Application", app: "Application",
                 canvas_node: "CanvasNode"):
        super().__init__(
            master,
            app,
            f"{canvas_node.core_node.name} Mobility Configuration",
            modal=True,
        )
        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:
            self.has_error = True
            show_grpc_error(e, self.app, self.app)
            self.destroy()

    def draw(self):
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)
        self.draw_apply_buttons()

    def draw_apply_buttons(self):
        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)

        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, padx=PADX, sticky="ew")

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky="ew")

    def click_apply(self):
        self.config_frame.parse_config()
        self.app.core.mobility_configs[self.node.id] = self.config
        self.destroy()
示例#17
0
class MobilityConfigDialog(Dialog):
    def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
        super().__init__(
            app, f"{canvas_node.core_node.name} Mobility Configuration")
        self.canvas_node: "CanvasNode" = canvas_node
        self.node: Node = canvas_node.core_node
        self.config_frame: Optional[ConfigFrame] = None
        self.has_error: bool = False
        try:
            config = self.canvas_node.mobility_config
            if not config:
                config = self.app.core.get_mobility_config(self.node.id)
            self.config: Dict[str, ConfigOption] = config
            self.draw()
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Get Mobility Config Error", e)
            self.has_error: bool = True
            self.destroy()

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky="nsew", pady=PADY)
        self.draw_apply_buttons()

    def draw_apply_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky="ew")
        for i in range(2):
            frame.columnconfigure(i, weight=1)

        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, padx=PADX, sticky="ew")

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky="ew")

    def click_apply(self) -> None:
        self.config_frame.parse_config()
        self.canvas_node.mobility_config = self.config
        self.destroy()
示例#18
0
class ConfigServiceConfigDialog(Dialog):
    def __init__(
        self, master: tk.BaseWidget, app: "Application", service_name: str, node: Node
    ) -> None:
        title = f"{service_name} Config Service"
        super().__init__(app, title, master=master)
        self.core: "CoreClient" = app.core
        self.node: Node = node
        self.service_name: str = service_name
        self.radiovar: tk.IntVar = tk.IntVar()
        self.radiovar.set(2)
        self.directories: List[str] = []
        self.templates: List[str] = []
        self.dependencies: List[str] = []
        self.executables: List[str] = []
        self.startup_commands: List[str] = []
        self.validation_commands: List[str] = []
        self.shutdown_commands: List[str] = []
        self.default_startup: List[str] = []
        self.default_validate: List[str] = []
        self.default_shutdown: List[str] = []
        self.validation_mode: Optional[ServiceValidationMode] = None
        self.validation_time: Optional[int] = None
        self.validation_period: tk.StringVar = tk.StringVar()
        self.modes: List[str] = []
        self.mode_configs: Dict[str, Dict[str, str]] = {}

        self.notebook: Optional[ttk.Notebook] = None
        self.templates_combobox: Optional[ttk.Combobox] = None
        self.modes_combobox: Optional[ttk.Combobox] = None
        self.startup_commands_listbox: Optional[tk.Listbox] = None
        self.shutdown_commands_listbox: Optional[tk.Listbox] = None
        self.validate_commands_listbox: Optional[tk.Listbox] = None
        self.validation_time_entry: Optional[ttk.Entry] = None
        self.validation_mode_entry: Optional[ttk.Entry] = None
        self.template_text: Optional[CodeText] = None
        self.validation_period_entry: Optional[ttk.Entry] = None
        self.original_service_files: Dict[str, str] = {}
        self.temp_service_files: Dict[str, str] = {}
        self.modified_files: Set[str] = set()
        self.config_frame: Optional[ConfigFrame] = None
        self.default_config: Dict[str, str] = {}
        self.config: Dict[str, ConfigOption] = {}
        self.has_error: bool = False
        self.load()
        if not self.has_error:
            self.draw()

    def load(self) -> None:
        try:
            self.core.start_session(definition=True)
            service = self.core.config_services[self.service_name]
            self.dependencies = service.dependencies[:]
            self.executables = service.executables[:]
            self.directories = service.directories[:]
            self.templates = service.files[:]
            self.startup_commands = service.startup[:]
            self.validation_commands = service.validate[:]
            self.shutdown_commands = service.shutdown[:]
            self.validation_mode = service.validation_mode
            self.validation_time = service.validation_timer
            self.validation_period.set(service.validation_period)

            defaults = self.core.client.get_config_service_defaults(self.service_name)
            self.original_service_files = defaults.templates
            self.temp_service_files = dict(self.original_service_files)
            self.modes = sorted(defaults.modes)
            self.mode_configs = defaults.modes
            self.config = ConfigOption.from_dict(defaults.config)
            self.default_config = {x.name: x.value for x in self.config.values()}
            service_config = self.node.config_service_configs.get(self.service_name)
            if service_config:
                for key, value in service_config.config.items():
                    self.config[key].value = value
                logger.info("default config: %s", self.default_config)
                for file, data in service_config.templates.items():
                    self.modified_files.add(file)
                    self.temp_service_files[file] = data
        except grpc.RpcError as e:
            self.app.show_grpc_exception("Get Config Service Error", e)
            self.has_error = True

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)

        # draw notebook
        self.notebook = ttk.Notebook(self.top)
        self.notebook.grid(sticky=tk.NSEW, pady=PADY)
        self.draw_tab_files()
        if self.config:
            self.draw_tab_config()
        self.draw_tab_startstop()
        self.draw_tab_validation()
        self.draw_buttons()

    def draw_tab_files(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Directories/Files")

        label = ttk.Label(
            tab, text="Directories and templates that will be used for this service."
        )
        label.grid(pady=PADY)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)
        label = ttk.Label(frame, text="Directories")
        label.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        directories_combobox = ttk.Combobox(
            frame, values=self.directories, state="readonly"
        )
        directories_combobox.grid(row=0, column=1, sticky=tk.EW, pady=PADY)
        if self.directories:
            directories_combobox.current(0)

        label = ttk.Label(frame, text="Templates")
        label.grid(row=1, column=0, sticky=tk.W, padx=PADX)
        self.templates_combobox = ttk.Combobox(
            frame, values=self.templates, state="readonly"
        )
        self.templates_combobox.bind(
            "<<ComboboxSelected>>", self.handle_template_changed
        )
        self.templates_combobox.grid(row=1, column=1, sticky=tk.EW, pady=PADY)

        self.template_text = CodeText(tab)
        self.template_text.grid(sticky=tk.NSEW)
        tab.rowconfigure(self.template_text.grid_info()["row"], weight=1)
        if self.templates:
            self.templates_combobox.current(0)
            self.template_text.text.delete(1.0, "end")
            self.template_text.text.insert(
                "end", self.temp_service_files[self.templates[0]]
            )
        self.template_text.text.bind("<FocusOut>", self.update_template_file_data)

    def draw_tab_config(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Configuration")

        if self.modes:
            frame = ttk.Frame(tab)
            frame.grid(sticky=tk.EW, pady=PADY)
            frame.columnconfigure(1, weight=1)
            label = ttk.Label(frame, text="Modes")
            label.grid(row=0, column=0, padx=PADX)
            self.modes_combobox = ttk.Combobox(
                frame, values=self.modes, state="readonly"
            )
            self.modes_combobox.bind("<<ComboboxSelected>>", self.handle_mode_changed)
            self.modes_combobox.grid(row=0, column=1, sticky=tk.EW, pady=PADY)

        logger.info("config service config: %s", self.config)
        self.config_frame = ConfigFrame(tab, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
        tab.rowconfigure(self.config_frame.grid_info()["row"], weight=1)

    def draw_tab_startstop(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.NSEW)
        tab.columnconfigure(0, weight=1)
        for i in range(3):
            tab.rowconfigure(i, weight=1)
        self.notebook.add(tab, text="Startup/Shutdown")
        commands = []
        # tab 3
        for i in range(3):
            label_frame = None
            if i == 0:
                label_frame = ttk.LabelFrame(
                    tab, text="Startup Commands", padding=FRAME_PAD
                )
                commands = self.startup_commands
            elif i == 1:
                label_frame = ttk.LabelFrame(
                    tab, text="Shutdown Commands", padding=FRAME_PAD
                )
                commands = self.shutdown_commands
            elif i == 2:
                label_frame = ttk.LabelFrame(
                    tab, text="Validation Commands", padding=FRAME_PAD
                )
                commands = self.validation_commands
            label_frame.columnconfigure(0, weight=1)
            label_frame.rowconfigure(0, weight=1)
            label_frame.grid(row=i, column=0, sticky=tk.NSEW, pady=PADY)
            listbox_scroll = ListboxScroll(label_frame)
            for command in commands:
                listbox_scroll.listbox.insert("end", command)
            listbox_scroll.listbox.config(height=4)
            listbox_scroll.grid(sticky=tk.NSEW)
            if i == 0:
                self.startup_commands_listbox = listbox_scroll.listbox
            elif i == 1:
                self.shutdown_commands_listbox = listbox_scroll.listbox
            elif i == 2:
                self.validate_commands_listbox = listbox_scroll.listbox

    def draw_tab_validation(self) -> None:
        tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
        tab.grid(sticky=tk.EW)
        tab.columnconfigure(0, weight=1)
        self.notebook.add(tab, text="Validation", sticky=tk.NSEW)

        frame = ttk.Frame(tab)
        frame.grid(sticky=tk.EW, pady=PADY)
        frame.columnconfigure(1, weight=1)

        label = ttk.Label(frame, text="Validation Time")
        label.grid(row=0, column=0, sticky=tk.W, padx=PADX)
        self.validation_time_entry = ttk.Entry(frame)
        self.validation_time_entry.insert("end", self.validation_time)
        self.validation_time_entry.config(state=tk.DISABLED)
        self.validation_time_entry.grid(row=0, column=1, sticky=tk.EW, pady=PADY)

        label = ttk.Label(frame, text="Validation Mode")
        label.grid(row=1, column=0, sticky=tk.W, padx=PADX)
        if self.validation_mode == ServiceValidationMode.BLOCKING:
            mode = "BLOCKING"
        elif self.validation_mode == ServiceValidationMode.NON_BLOCKING:
            mode = "NON_BLOCKING"
        else:
            mode = "TIMER"
        self.validation_mode_entry = ttk.Entry(
            frame, textvariable=tk.StringVar(value=mode)
        )
        self.validation_mode_entry.insert("end", mode)
        self.validation_mode_entry.config(state=tk.DISABLED)
        self.validation_mode_entry.grid(row=1, column=1, sticky=tk.EW, pady=PADY)

        label = ttk.Label(frame, text="Validation Period")
        label.grid(row=2, column=0, sticky=tk.W, padx=PADX)
        self.validation_period_entry = ttk.Entry(
            frame, state=tk.DISABLED, textvariable=self.validation_period
        )
        self.validation_period_entry.grid(row=2, column=1, sticky=tk.EW, pady=PADY)

        label_frame = ttk.LabelFrame(tab, text="Executables", padding=FRAME_PAD)
        label_frame.grid(sticky=tk.NSEW, pady=PADY)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        listbox_scroll = ListboxScroll(label_frame)
        listbox_scroll.grid(sticky=tk.NSEW)
        tab.rowconfigure(listbox_scroll.grid_info()["row"], weight=1)
        for executable in self.executables:
            listbox_scroll.listbox.insert("end", executable)

        label_frame = ttk.LabelFrame(tab, text="Dependencies", padding=FRAME_PAD)
        label_frame.grid(sticky=tk.NSEW, pady=PADY)
        label_frame.columnconfigure(0, weight=1)
        label_frame.rowconfigure(0, weight=1)
        listbox_scroll = ListboxScroll(label_frame)
        listbox_scroll.grid(sticky=tk.NSEW)
        tab.rowconfigure(listbox_scroll.grid_info()["row"], weight=1)
        for dependency in self.dependencies:
            listbox_scroll.listbox.insert("end", dependency)

    def draw_buttons(self) -> None:
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(4):
            frame.columnconfigure(i, weight=1)
        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Defaults", command=self.click_defaults)
        button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Copy...", command=self.click_copy)
        button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=3, sticky=tk.EW)

    def click_apply(self) -> None:
        current_listbox = self.master.current.listbox
        if not self.is_custom():
            self.node.config_service_configs.pop(self.service_name, None)
            current_listbox.itemconfig(current_listbox.curselection()[0], bg="")
            self.destroy()
            return
        service_config = self.node.config_service_configs.setdefault(
            self.service_name, ConfigServiceData()
        )
        if self.config_frame:
            self.config_frame.parse_config()
            service_config.config = {x.name: x.value for x in self.config.values()}
        for file in self.modified_files:
            service_config.templates[file] = self.temp_service_files[file]
        all_current = current_listbox.get(0, tk.END)
        current_listbox.itemconfig(all_current.index(self.service_name), bg="green")
        self.destroy()

    def handle_template_changed(self, event: tk.Event) -> None:
        template = self.templates_combobox.get()
        self.template_text.text.delete(1.0, "end")
        self.template_text.text.insert("end", self.temp_service_files[template])

    def handle_mode_changed(self, event: tk.Event) -> None:
        mode = self.modes_combobox.get()
        config = self.mode_configs[mode]
        logger.info("mode config: %s", config)
        self.config_frame.set_values(config)

    def update_template_file_data(self, event: tk.Event) -> None:
        scrolledtext = event.widget
        template = self.templates_combobox.get()
        self.temp_service_files[template] = scrolledtext.get(1.0, "end")
        if self.temp_service_files[template] != self.original_service_files[template]:
            self.modified_files.add(template)
        else:
            self.modified_files.discard(template)

    def is_custom(self) -> bool:
        has_custom_templates = len(self.modified_files) > 0
        has_custom_config = False
        if self.config_frame:
            current = self.config_frame.parse_config()
            has_custom_config = self.default_config != current
        return has_custom_templates or has_custom_config

    def click_defaults(self) -> None:
        self.node.config_service_configs.pop(self.service_name, None)
        logger.info(
            "cleared config service config: %s", self.node.config_service_configs
        )
        self.temp_service_files = dict(self.original_service_files)
        filename = self.templates_combobox.get()
        self.template_text.text.delete(1.0, "end")
        self.template_text.text.insert("end", self.temp_service_files[filename])
        if self.config_frame:
            logger.info("resetting defaults: %s", self.default_config)
            self.config_frame.set_values(self.default_config)

    def click_copy(self) -> None:
        pass

    def append_commands(
        self, commands: List[str], listbox: tk.Listbox, to_add: List[str]
    ) -> None:
        for cmd in to_add:
            commands.append(cmd)
            listbox.insert(tk.END, cmd)
示例#19
0
class WlanConfigDialog(Dialog):
    def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
        super().__init__(app,
                         f"{canvas_node.core_node.name} WLAN Configuration")
        self.canvas: "CanvasGraph" = app.canvas
        self.canvas_node: "CanvasNode" = canvas_node
        self.node: Node = canvas_node.core_node
        self.config_frame: Optional[ConfigFrame] = None
        self.range_entry: Optional[ttk.Entry] = None
        self.has_error: bool = False
        self.ranges: Dict[int, int] = {}
        self.positive_int: int = self.app.master.register(
            self.validate_and_update)
        try:
            config = self.node.wlan_config
            if not config:
                config = self.app.core.get_wlan_config(self.node.id)
            self.config: Dict[str, ConfigOption] = config
            self.init_draw_range()
            self.draw()
        except grpc.RpcError as e:
            self.app.show_grpc_exception("WLAN Config Error", e)
            self.has_error: bool = True
            self.destroy()

    def init_draw_range(self) -> None:
        if self.canvas_node.id in self.canvas.wireless_network:
            for cid in self.canvas.wireless_network[self.canvas_node.id]:
                x, y = self.canvas.coords(cid)
                range_id = self.canvas.create_oval(x,
                                                   y,
                                                   x,
                                                   y,
                                                   width=RANGE_WIDTH,
                                                   outline=RANGE_COLOR,
                                                   tags="range")
                self.ranges[cid] = range_id

    def draw(self) -> None:
        self.top.columnconfigure(0, weight=1)
        self.top.rowconfigure(0, weight=1)
        self.config_frame = ConfigFrame(self.top, self.app, self.config)
        self.config_frame.draw_config()
        self.config_frame.grid(sticky=tk.NSEW, pady=PADY)
        self.draw_apply_buttons()
        self.top.bind("<Destroy>", self.remove_ranges)

    def draw_apply_buttons(self) -> None:
        """
        create node configuration options
        """
        frame = ttk.Frame(self.top)
        frame.grid(sticky=tk.EW)
        for i in range(2):
            frame.columnconfigure(i, weight=1)

        self.range_entry = self.config_frame.winfo_children(
        )[0].frame.winfo_children()[-1]
        self.range_entry.config(validatecommand=(self.positive_int, "%P"))

        button = ttk.Button(frame, text="Apply", command=self.click_apply)
        button.grid(row=0, column=0, padx=PADX, sticky=tk.EW)

        button = ttk.Button(frame, text="Cancel", command=self.destroy)
        button.grid(row=0, column=1, sticky=tk.EW)

    def click_apply(self) -> None:
        """
        retrieve user's wlan configuration and store the new configuration values
        """
        config = self.config_frame.parse_config()
        self.node.wlan_config = self.config
        if self.app.core.is_runtime():
            session_id = self.app.core.session.id
            self.app.core.client.set_wlan_config(session_id, self.node.id,
                                                 config)
        self.remove_ranges()
        self.destroy()

    def remove_ranges(self, event=None) -> None:
        for cid in self.canvas.find_withtag("range"):
            self.canvas.delete(cid)
        self.ranges.clear()

    def validate_and_update(self, s: str) -> bool:
        """
        custom validation to also redraw the mdr ranges when the range value changes
        """
        if len(s) == 0:
            return True
        try:
            int_value = int(s) / 2
            if int_value >= 0:
                net_range = int_value * self.canvas.ratio
                if self.canvas_node.id in self.canvas.wireless_network:
                    for cid in self.canvas.wireless_network[
                            self.canvas_node.id]:
                        x, y = self.canvas.coords(cid)
                        self.canvas.coords(
                            self.ranges[cid],
                            x - net_range,
                            y - net_range,
                            x + net_range,
                            y + net_range,
                        )
                return True
            return False
        except ValueError:
            return False