diff --git a/src/config_editor.py b/src/config_editor.py index 831cee1..5ad3f50 100644 --- a/src/config_editor.py +++ b/src/config_editor.py @@ -1,5 +1,7 @@ """Configuration editor for Road Core service.""" +from typing import Optional + import yaml from gui.main_window import MainWindow @@ -10,32 +12,34 @@ class ConfigEditor: """Class representing instances of configuration editor.""" - def __init__(self): + def __init__(self) -> None: """Initialize configuration editor.""" self.configuration = None - self.filename = None + self.filename: Optional[str] = None - def new_configuration(self): + def new_configuration(self) -> None: """Create new configuration to be edited.""" self.configuration = None - def load_configuration(self, filename): + def load_configuration(self, filename: str) -> None: """Load configuration from YAML file.""" with open(filename, encoding="utf-8") as fin: self.configuration = yaml.safe_load(fin) self.filename = filename - def save_configuration_as(self, filename): + def save_configuration_as(self, filename: str) -> None: """Store configuration into YAML file.""" with open(filename, "w", encoding="utf-8") as fout: yaml.dump(self.configuration, fout) - def save_configuration(self): + def save_configuration(self) -> None: """Store configuration into YAML file.""" + if self.filename is None: + return with open(self.filename, "w", encoding="utf-8") as fout: yaml.dump(self.configuration, fout) - def check_configuration(self): + def check_configuration(self) -> None: """Check if configuration is correct one.""" diff --git a/src/gui/dialogs/about_dialog.py b/src/gui/dialogs/about_dialog.py index d804a45..a47b3bb 100644 --- a/src/gui/dialogs/about_dialog.py +++ b/src/gui/dialogs/about_dialog.py @@ -3,7 +3,7 @@ from tkinter import messagebox -def about(): +def about() -> None: """Show 'about' dialog.""" messagebox.showinfo( "Config editor", "Configuration editor for the Road Core service" diff --git a/src/gui/dialogs/auth_dialog.py b/src/gui/dialogs/auth_dialog.py index 5a8254f..b038d95 100644 --- a/src/gui/dialogs/auth_dialog.py +++ b/src/gui/dialogs/auth_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class AuthDialog(tkinter.Toplevel): """Dialog for editing authentication configuration.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize authentication configuration dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Authentication configuration") diff --git a/src/gui/dialogs/cache_dialog.py b/src/gui/dialogs/cache_dialog.py index 40d7ef4..158711b 100644 --- a/src/gui/dialogs/cache_dialog.py +++ b/src/gui/dialogs/cache_dialog.py @@ -3,11 +3,13 @@ import tkinter from tkinter import ttk +from gui.icons import Icons + class ConversationCacheDialog(tkinter.Toplevel): """Dialog for editing conversation settings.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize dialog for editing conversation settings.""" tkinter.Toplevel.__init__(self, parent) self.title("Conversation cache") @@ -24,19 +26,19 @@ def __init__(self, parent, icons): self.grab_set() # UI groups - self.group = tkinter.LabelFrame(self, text="Conversation cache", padx=5, pady=8) + self.uigroup = tkinter.LabelFrame(self, text="Conversation cache", padx=5, pady=8) - label1 = tkinter.Label(self.group, text="Type") + label1 = tkinter.Label(self.uigroup, text="Type") label1.grid(row=1, column=1, sticky="W", padx=5, pady=5) cache_types = ("In-memory", "PostgreSQL", "Redis") - cache_type = tkinter.StringVar(self.group, cache_types[0], "cache_type") + cache_type = tkinter.StringVar(self.uigroup, cache_types[0], "cache_type") print(cache_type) cb1 = ttk.Combobox( - self.group, + self.uigroup, values=cache_types, # textvariable=app_log_levels, state="readonly", @@ -54,7 +56,7 @@ def __init__(self, parent, icons): ) # UI groups placement - self.group.grid(row=1, column=1, sticky="NSWE", padx=5, pady=5) + self.uigroup.grid(row=1, column=1, sticky="NSWE", padx=5, pady=5) ok_button.grid(row=2, column=1, sticky="W", padx=10, pady=10) diff --git a/src/gui/dialogs/check_configuration.py b/src/gui/dialogs/check_configuration.py index fc5ce3b..56fa1e5 100644 --- a/src/gui/dialogs/check_configuration.py +++ b/src/gui/dialogs/check_configuration.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class CheckConfigurationDialog(tkinter.Toplevel): """Dialog for checking the configuration.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize dialog for checking the configuration.""" tkinter.Toplevel.__init__(self, parent) self.title("Check configuration") diff --git a/src/gui/dialogs/data_collection_dialog.py b/src/gui/dialogs/data_collection_dialog.py index 2266264..11db1bb 100644 --- a/src/gui/dialogs/data_collection_dialog.py +++ b/src/gui/dialogs/data_collection_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class DataCollectionDialog(tkinter.Toplevel): """Data collection dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize data collection dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Data collection settings") diff --git a/src/gui/dialogs/default_model_dialog.py b/src/gui/dialogs/default_model_dialog.py index 19cd51c..f52baa0 100644 --- a/src/gui/dialogs/default_model_dialog.py +++ b/src/gui/dialogs/default_model_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class DefaultModelSelection(tkinter.Toplevel): """Default model selection dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize default model selection dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Default model selection") diff --git a/src/gui/dialogs/default_provider_dialog.py b/src/gui/dialogs/default_provider_dialog.py index 789a914..01544f7 100644 --- a/src/gui/dialogs/default_provider_dialog.py +++ b/src/gui/dialogs/default_provider_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class DefaultProviderSelection(tkinter.Toplevel): """Default provider selection dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize default provider selection dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Default provider selection") diff --git a/src/gui/dialogs/edit_dialog.py b/src/gui/dialogs/edit_dialog.py index 5e72884..6c67900 100644 --- a/src/gui/dialogs/edit_dialog.py +++ b/src/gui/dialogs/edit_dialog.py @@ -2,6 +2,7 @@ import tkinter from tkinter import ttk +from typing import Optional from gui.dialogs.auth_dialog import AuthDialog from gui.dialogs.cache_dialog import ConversationCacheDialog @@ -12,6 +13,7 @@ from gui.dialogs.logging_dialog import LoggingDialog from gui.dialogs.security_profile_dialog import TLSSecurityProfileDialog from gui.dialogs.tls_dialog import TLSConfigurationDialog +from gui.icons import Icons BUTTON_WIDTH = 100 @@ -19,28 +21,30 @@ class EditDialog(tkinter.Toplevel): """Implementation of configuration editor.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize the dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Configuration editor") self.icons = icons self.parent = parent - self.group1 = None - self.group2 = None - self.group3 = None + self.group1: Optional[tkinter.LabelFrame] = None + self.group2: Optional[tkinter.LabelFrame] = None + self.group3: Optional[tkinter.LabelFrame] = None # don't display the dialog in list of opened windows self.transient(parent) self.add_widgets() self.set_dialog_properties() - def add_widgets(self): + def add_widgets(self) -> None: """Add all widgets on the dialog.""" self.add_llm_group() self.add_service_settings_group() self.add_devel_settings_group() # UI groups placement + if self.group1 is None or self.group2 is None or self.group3 is None: + return self.group1.grid(row=1, column=1, sticky="NSWE", padx=5, pady=5) self.group2.grid(row=1, column=2, sticky="NSWE", padx=5, pady=5) self.group3.grid(row=1, column=3, sticky="NSWE", padx=5, pady=5) @@ -68,7 +72,7 @@ def add_widgets(self): # set the focus ok_button.focus_set() - def set_dialog_properties(self): + def set_dialog_properties(self) -> None: """Set edit dialog properties.""" # close the dialog on 'x' click self.protocol("WM_DELETE_WINDOW", self.destroy) @@ -80,7 +84,7 @@ def set_dialog_properties(self): self.bind("", lambda _: self.ok()) self.bind("", lambda _: self.destroy()) - def add_llm_group(self): + def add_llm_group(self) -> None: """Add LLM group widgets onto the dialog.""" # UI groups self.group1 = tkinter.LabelFrame(self, text="LLM section", padx=5, pady=8) @@ -96,7 +100,7 @@ def add_llm_group(self): ) button_new_llm.grid(row=1, column=1, sticky="WE", padx=5, pady=5) - def add_service_settings_group(self): + def add_service_settings_group(self) -> None: """Add service settings widgets onto the dialog.""" self.group2 = tkinter.LabelFrame(self, text="Service settings", padx=5, pady=8) # service settings @@ -199,7 +203,9 @@ def add_service_settings_group(self): label9 = tkinter.Label(self.group2, text="Query validation method") label9.grid(row=9, column=1, sticky="W", padx=5, pady=5) query_validation_methods = ("LLM", "Keyword") - query_validation_method = query_validation_methods[0] + query_validation_method = tkinter.StringVar( + self.group2, query_validation_methods[0], "query_validation_method" + ) cb = ttk.Combobox( self.group2, @@ -210,7 +216,7 @@ def add_service_settings_group(self): cb.current(0) cb.grid(row=9, column=2, sticky="W", padx=5, pady=5) - def add_devel_settings_group(self): + def add_devel_settings_group(self) -> None: """Add devel settings widgets onto the dialog.""" self.group3 = tkinter.LabelFrame(self, text="Devel settings", padx=5, pady=8) # devel settings diff --git a/src/gui/dialogs/help_dialog.py b/src/gui/dialogs/help_dialog.py index 7e375a7..4bc7514 100644 --- a/src/gui/dialogs/help_dialog.py +++ b/src/gui/dialogs/help_dialog.py @@ -1,12 +1,13 @@ """Help dialog implementation.""" import tkinter +from typing import Optional class HelpDialog(tkinter.Toplevel): """Help dialog implementation.""" - def __init__(self, parent): + def __init__(self, parent: Optional[tkinter.Toplevel]) -> None: """Perform initialization of help dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Nápověda") @@ -46,11 +47,11 @@ def __init__(self, parent): # close the dialog on 'x' click self.protocol("WM_DELETE_WINDOW", self.destroy) - def ok(self): + def ok(self) -> None: """Ok button handler.""" self.destroy() -def show_help(): +def show_help() -> None: """Display help dialog.""" HelpDialog(None) diff --git a/src/gui/dialogs/llm_dialog.py b/src/gui/dialogs/llm_dialog.py index 18a090e..42d2fec 100644 --- a/src/gui/dialogs/llm_dialog.py +++ b/src/gui/dialogs/llm_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class LLMDialog(tkinter.Toplevel): """New LLM dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize new LLM dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("New LLM") diff --git a/src/gui/dialogs/logging_dialog.py b/src/gui/dialogs/logging_dialog.py index 6686796..4164b3b 100644 --- a/src/gui/dialogs/logging_dialog.py +++ b/src/gui/dialogs/logging_dialog.py @@ -3,11 +3,13 @@ import tkinter from tkinter import ttk +from gui.icons import Icons + class LoggingDialog(tkinter.Toplevel): """Logging dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize logging dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("Logging settings") @@ -24,11 +26,11 @@ def __init__(self, parent, icons): self.grab_set() # UI groups - self.group = tkinter.LabelFrame(self, text="Logging levels", padx=5, pady=8) + self.uigroup = tkinter.LabelFrame(self, text="Logging levels", padx=5, pady=8) - label1 = tkinter.Label(self.group, text="Application") - label2 = tkinter.Label(self.group, text="Libraries") - label3 = tkinter.Label(self.group, text="Uvicorn") + label1 = tkinter.Label(self.uigroup, text="Application") + label2 = tkinter.Label(self.uigroup, text="Libraries") + label3 = tkinter.Label(self.uigroup, text="Uvicorn") label1.grid(row=1, column=1, sticky="W", padx=5, pady=5) label2.grid(row=2, column=1, sticky="W", padx=5, pady=5) @@ -37,11 +39,11 @@ def __init__(self, parent, icons): debug_levels = ("Not set", "Debug", "Info", "Warning", "Error", "Critical") app_log_levels = tkinter.StringVar( - self.group, debug_levels[0], "app_log_levels" + self.uigroup, debug_levels[0], "app_log_levels" ) print(app_log_levels) cb1 = ttk.Combobox( - self.group, + self.uigroup, values=debug_levels, # textvariable=app_log_levels, state="readonly", @@ -50,11 +52,11 @@ def __init__(self, parent, icons): cb1.grid(row=1, column=2, sticky="W", padx=5, pady=5) lib_log_levels = tkinter.StringVar( - self.group, debug_levels[0], "lib_log_levels" + self.uigroup, debug_levels[0], "lib_log_levels" ) print(lib_log_levels) cb2 = ttk.Combobox( - self.group, + self.uigroup, values=debug_levels, # textvariable=lib_log_levels, state="readonly", @@ -63,11 +65,11 @@ def __init__(self, parent, icons): cb2.grid(row=2, column=2, sticky="W", padx=5, pady=5) uvicorn_log_levels = tkinter.StringVar( - self.group, debug_levels[0], "uvicorn_log_levels" + self.uigroup, debug_levels[0], "uvicorn_log_levels" ) print(uvicorn_log_levels) cb3 = ttk.Combobox( - self.group, + self.uigroup, values=debug_levels, # textvariable=uvicorn_log_levels, state="readonly", @@ -76,7 +78,7 @@ def __init__(self, parent, icons): cb3.grid(row=3, column=2, sticky="W", padx=5, pady=5) # UI groups placement - self.group.grid(row=1, column=1, sticky="NSWE", padx=5, pady=5) + self.uigroup.grid(row=1, column=1, sticky="NSWE", padx=5, pady=5) ok_button = tkinter.Button( self, diff --git a/src/gui/dialogs/security_profile_dialog.py b/src/gui/dialogs/security_profile_dialog.py index 2481f0b..a52afca 100644 --- a/src/gui/dialogs/security_profile_dialog.py +++ b/src/gui/dialogs/security_profile_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class TLSSecurityProfileDialog(tkinter.Toplevel): """Security profile dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize security profile dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("TLS security profile") diff --git a/src/gui/dialogs/tls_dialog.py b/src/gui/dialogs/tls_dialog.py index b0e9265..df7f140 100644 --- a/src/gui/dialogs/tls_dialog.py +++ b/src/gui/dialogs/tls_dialog.py @@ -2,11 +2,13 @@ import tkinter +from gui.icons import Icons + class TLSConfigurationDialog(tkinter.Toplevel): """TLS configuration dialog.""" - def __init__(self, parent, icons): + def __init__(self, parent: tkinter.Toplevel, icons: Icons) -> None: """Initialize TLS configuration dialog.""" tkinter.Toplevel.__init__(self, parent) self.title("TLS configuration") diff --git a/src/gui/icons.py b/src/gui/icons.py index d2a96e9..48eed08 100644 --- a/src/gui/icons.py +++ b/src/gui/icons.py @@ -21,7 +21,7 @@ class Icons: """All icons used on the GUI.""" - def __init__(self): + def __init__(self) -> None: """Initialize all icons and convert them to PhotoImage.""" self.exit_icon = tkinter.PhotoImage(data=icons.application_exit.icon) self.help_faq_icon = tkinter.PhotoImage(data=icons.help_faq.icon) diff --git a/src/gui/main_window.py b/src/gui/main_window.py index da2ca0b..46df767 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -2,6 +2,7 @@ import tkinter from tkinter import filedialog, messagebox +from typing import Any from gui.dialogs.edit_dialog import EditDialog from gui.icons import Icons @@ -13,7 +14,7 @@ class MainWindow: """Main window shown on screen.""" - def __init__(self, config_editor): + def __init__(self, config_editor: Any) -> None: """Initialize main window.""" self.config_editor = config_editor self.root = tkinter.Tk() @@ -34,11 +35,11 @@ def __init__(self, config_editor): self.root.geometry("480x320") # EditDialog(self.root, self.icons) - def show(self): + def show(self) -> None: """Display the main window on screen.""" self.root.mainloop() - def quit(self): + def quit(self) -> None: """Display message box whether to quit the application.""" answer = messagebox.askyesno( "Do you want to quit the program?", "Do you want to quit the program?" @@ -46,12 +47,12 @@ def quit(self): if answer: self.root.quit() - def configure_grid(self): + def configure_grid(self) -> None: """Configure grid on canvas.""" tkinter.Grid.rowconfigure(self.root, 2, weight=1) tkinter.Grid.columnconfigure(self.root, 2, weight=1) - def new_configuration(self): + def new_configuration(self) -> None: """Initialize new configuration.""" answer = messagebox.askyesno( "Clear current configuration?", "Clear current configuration?" @@ -59,11 +60,11 @@ def new_configuration(self): if answer: self.config_editor.new_configuration() - def load_configuration(self): + def load_configuration(self) -> None: """Load configuration from YAML file.""" filetypes = [("YAML files", "*.yaml"), ("YAML files", "*.yaml")] dialog = filedialog.Open(self.root, filetypes=filetypes) - filename = dialog.show() + filename = dialog.show() # type: ignore [no-untyped-call] if filename is not None and filename != "": try: self.config_editor.load_configuration(filename) @@ -72,7 +73,7 @@ def load_configuration(self): messagebox.showerror("Configuration loading failed", f"Failure {e}") print(e) - def save_configuration(self): + def save_configuration(self) -> None: """Save configuration into YAML file.""" try: self.config_editor.save_configuration() @@ -81,11 +82,11 @@ def save_configuration(self): messagebox.showerror("Configuration saving failed", f"Failure {e}") print(e) - def save_as_configuration(self): + def save_as_configuration(self) -> None: """Save configuration into specified YAML file.""" filetypes = [("YAML files", "*.yaml"), ("YAML files", "*.yaml")] dialog = filedialog.SaveAs(self.root, filetypes=filetypes) - filename = dialog.show() + filename = dialog.show() # type: ignore [no-untyped-call] if filename is not None and filename != "": try: self.config_editor.save_configuration_as(filename) @@ -94,11 +95,11 @@ def save_as_configuration(self): messagebox.showerror("Configuration saving failed", f"Failure {e}") print(e) - def edit_configuration(self): + def edit_configuration(self) -> None: """Edit configuration using the specialized dialog.""" EditDialog(self.root, self.icons) - def check_configuration(self): + def check_configuration(self) -> None: """Check configuration.""" result = self.config_editor.check_configuration() print(result) diff --git a/src/gui/menubar.py b/src/gui/menubar.py index ae68d34..62ac0e2 100644 --- a/src/gui/menubar.py +++ b/src/gui/menubar.py @@ -1,6 +1,7 @@ """Menu bar displayed on the main window.""" import tkinter +from typing import Any from gui.dialogs.about_dialog import about from gui.dialogs.help_dialog import show_help @@ -9,7 +10,7 @@ class Menubar(tkinter.Menu): """Menu bar displayed on the main window.""" - def __init__(self, parent, main_window): + def __init__(self, parent: tkinter.Toplevel, main_window: Any) -> None: """Initialize the menu bar.""" super().__init__(tearoff=0) diff --git a/src/gui/status_bar.py b/src/gui/status_bar.py index 0b5698f..f939100 100644 --- a/src/gui/status_bar.py +++ b/src/gui/status_bar.py @@ -1,6 +1,7 @@ """Status bar displayed in the main window.""" import tkinter +from typing import Any class StatusBar(tkinter.Frame): @@ -12,7 +13,7 @@ def __init__(self, master: tkinter.Tk) -> None: self.label = tkinter.Label(self, bd=1, relief=tkinter.SUNKEN, anchor=tkinter.W) self.label.pack(fill=tkinter.X) - def set(self, string_format, *args): + def set(self, string_format: str, *args: Any) -> None: """Set status bar messages.""" self.label.config(text=string_format % args) self.label.update_idletasks() diff --git a/src/gui/toolbar.py b/src/gui/toolbar.py index 0f4e71a..eaa09e2 100644 --- a/src/gui/toolbar.py +++ b/src/gui/toolbar.py @@ -8,7 +8,7 @@ class Toolbar(tkinter.LabelFrame): """Toolbar displayed on the main window.""" - def __init__(self, parent: tkinter.Tk, main_window) -> None: + def __init__(self, parent: tkinter.Tk, main_window) -> None: # type: ignore [no-untyped-def] """Initialize the toolbar.""" super().__init__(parent, text="Tools", padx=5, pady=5) @@ -99,7 +99,7 @@ def __init__(self, parent: tkinter.Tk, main_window) -> None: self.button_quit.grid(column=10, row=1) @staticmethod - def disable_button(button): + def disable_button(button: tkinter.Button) -> None: """Disable specified button on toolbar.""" button["state"] = "disabled" diff --git a/src/gui/tooltip.py b/src/gui/tooltip.py index 9d0fefe..80791ca 100644 --- a/src/gui/tooltip.py +++ b/src/gui/tooltip.py @@ -20,7 +20,7 @@ def __init__(self, widget: tkinter.Button, text: str = "widget info") -> None: self.widget.bind("", self.leave) self.widget.bind("", self.leave) self.id: Optional[str] = None - self.tw = None + self.tw: Optional[tkinter.Toplevel] = None def enter(self, event: tkinter.Event | None = None) -> None: """Handle the event: cursor pointer moves to the tooltip area.""" @@ -43,10 +43,10 @@ def unschedule(self) -> None: if current_id: self.widget.after_cancel(current_id) - def showtip(self, event=None): + def showtip(self, event: Optional[tkinter.Event]=None) -> None: """Show the tooltip on screen.""" x = y = 0 - x, y, _, _ = self.widget.bbox("insert") + x, y, _, _ = self.widget.bbox() # type: ignore [misc] x += self.widget.winfo_rootx() + 25 y += self.widget.winfo_rooty() + 20 # creates a toplevel window