From 7f479b0104f17b66c2bf0b0a39dfa21de0c2646d Mon Sep 17 00:00:00 2001 From: Debanjum Singh Solanky Date: Mon, 15 Aug 2022 22:57:56 +0300 Subject: [PATCH] Improve Displaying Error to User on Khoj window in Desktop GUI - Show a helpful error message in the GUI to the user, instead of the crashing if loading config fails, for e.g if file wasn't found - Collate GUI errors into an ErrorType enum class - Remove previous error messages before showing the new one --- src/interface/desktop/main_window.py | 46 +++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/interface/desktop/main_window.py b/src/interface/desktop/main_window.py index e5a82b7e..9f2b0544 100644 --- a/src/interface/desktop/main_window.py +++ b/src/interface/desktop/main_window.py @@ -1,4 +1,5 @@ # Standard Packages +from enum import Enum from pathlib import Path from copy import deepcopy import webbrowser @@ -152,11 +153,21 @@ class MainWindow(QtWidgets.QMainWindow): def add_error_message(self, message: str): "Add Error Message to Configure Screen" - error_message = QtWidgets.QLabel() - error_message.setWordWrap(True) - error_message.setText(message) - error_message.setStyleSheet("color: red") - self.layout.addWidget(error_message) + # Remove any existing error messages + for message_prefix in ErrorType: + for i in reversed(range(self.layout.count())): + current_widget = self.layout.itemAt(i).widget() + if isinstance(current_widget, QtWidgets.QLabel) and current_widget.text().startswith(message_prefix.value): + self.layout.removeWidget(current_widget) + current_widget.deleteLater() + + # Add new error message + if message: + error_message = QtWidgets.QLabel() + error_message.setWordWrap(True) + error_message.setText(message) + error_message.setStyleSheet("color: red") + self.layout.addWidget(error_message) def update_search_settings(self): "Update config with search settings from UI" @@ -196,22 +207,17 @@ class MainWindow(QtWidgets.QMainWindow): self.new_config['processor'][child.processor_type.value]['openai-api-key'] = child.input_field.toPlainText() if child.input_field.toPlainText() != '' else None def save_settings_to_file(self) -> bool: + "Save validated settings to file" # Validate config before writing to file try: yaml_utils.parse_config_from_string(self.new_config) except Exception as e: print(f"Error validating config: {e}") - self.add_error_message(f"Error validating config: {e}") + self.add_error_message(f"{ErrorType.ConfigValidationError.value}: {e}") return False - else: - # Remove error message if present - for i in range(self.layout.count()): - current_widget = self.layout.itemAt(i).widget() - if isinstance(current_widget, QtWidgets.QLabel) and current_widget.text().startswith("Error validating config:"): - self.layout.removeWidget(current_widget) - current_widget.deleteLater() # Save the config to app config file + self.add_error_message(None) yaml_utils.save_config_to_file(self.new_config, self.config_file) return True @@ -238,6 +244,7 @@ class MainWindow(QtWidgets.QMainWindow): self.thread.started.connect(self.settings_loader.run) self.settings_loader.finished.connect(self.thread.quit) self.settings_loader.finished.connect(self.settings_loader.deleteLater) + self.settings_loader.error.connect(self.add_error_message) self.thread.finished.connect(self.thread.deleteLater) # Start thread @@ -257,6 +264,7 @@ class MainWindow(QtWidgets.QMainWindow): class SettingsLoader(QObject): "Load Settings Thread" finished = pyqtSignal() + error = pyqtSignal(str) def __init__(self, load_settings_func): super(SettingsLoader, self).__init__() @@ -264,7 +272,12 @@ class SettingsLoader(QObject): def run(self): "Load Settings" - self.load_settings_func() + try: + self.load_settings_func() + except FileNotFoundError as e: + self.error.emit(f"{ErrorType.ConfigLoadingError.value}: {e}") + else: + self.error.emit(None) self.finished.emit() @@ -278,3 +291,8 @@ class ProcessorCheckBox(QtWidgets.QCheckBox): def __init__(self, text, processor_type: ProcessorType, parent=None): self.processor_type = processor_type super(ProcessorCheckBox, self).__init__(text, parent=parent) + +class ErrorType(Enum): + "Error Types" + ConfigLoadingError = "Config Loading Error" + ConfigValidationError = "Config Validation Error"