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
This commit is contained in:
Debanjum Singh Solanky 2022-08-15 22:57:56 +03:00
parent 873bb9dd97
commit 7f479b0104

View file

@ -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"