mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-09 13:25:11 +00:00
Convert Configure Screen into the Main Application Window
- What
- Convert the config screen into the main application window
with configuration as just one of the functionality it provides
- Rename config screen to main window to match new designation
- Why
- System Tray isn't available everywhere (e.g Linux)
- This requires moving functionality into a normal window for cross-compat
This commit is contained in:
@@ -18,7 +18,7 @@ from src.utils.config import SearchType, ProcessorType
|
|||||||
from src.utils.helpers import merge_dicts, resolve_absolute_path
|
from src.utils.helpers import merge_dicts, resolve_absolute_path
|
||||||
|
|
||||||
|
|
||||||
class ConfigureScreen(QtWidgets.QDialog):
|
class MainWindow(QtWidgets.QMainWindow):
|
||||||
"""Create Window to Configure Khoj
|
"""Create Window to Configure Khoj
|
||||||
Allow user to
|
Allow user to
|
||||||
1. Configure content types to search
|
1. Configure content types to search
|
||||||
@@ -26,8 +26,8 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
3. Save the configuration to khoj.yml
|
3. Save the configuration to khoj.yml
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, config_file: Path, parent=None):
|
def __init__(self, config_file: Path):
|
||||||
super(ConfigureScreen, self).__init__(parent=parent)
|
super(MainWindow, self).__init__()
|
||||||
self.config_file = config_file
|
self.config_file = config_file
|
||||||
|
|
||||||
# Load config from existing config, if exists, else load from default config
|
# Load config from existing config, if exists, else load from default config
|
||||||
@@ -45,24 +45,31 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
self.setFixedWidth(600)
|
self.setFixedWidth(600)
|
||||||
|
|
||||||
# Initialize Configure Window Layout
|
# Initialize Configure Window Layout
|
||||||
layout = QtWidgets.QVBoxLayout()
|
self.layout = QtWidgets.QVBoxLayout()
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
# Add Settings Panels for each Search Type to Configure Window Layout
|
# Add Settings Panels for each Search Type to Configure Window Layout
|
||||||
self.search_settings_panels = []
|
self.search_settings_panels = []
|
||||||
for search_type in SearchType:
|
for search_type in SearchType:
|
||||||
current_content_config = self.current_config['content-type'].get(search_type, {})
|
current_content_config = self.current_config['content-type'].get(search_type, {})
|
||||||
self.search_settings_panels += [self.add_settings_panel(current_content_config, search_type, layout)]
|
self.search_settings_panels += [self.add_settings_panel(current_content_config, search_type)]
|
||||||
|
|
||||||
# Add Conversation Processor Panel to Configure Screen
|
# Add Conversation Processor Panel to Configure Screen
|
||||||
self.processor_settings_panels = []
|
self.processor_settings_panels = []
|
||||||
conversation_type = ProcessorType.Conversation
|
conversation_type = ProcessorType.Conversation
|
||||||
current_conversation_config = self.current_config['processor'].get(conversation_type, {})
|
current_conversation_config = self.current_config['processor'].get(conversation_type, {})
|
||||||
self.processor_settings_panels += [self.add_processor_panel(current_conversation_config, conversation_type, layout)]
|
self.processor_settings_panels += [self.add_processor_panel(current_conversation_config, conversation_type)]
|
||||||
|
|
||||||
self.add_action_panel(layout)
|
# Add Action Buttons Panel
|
||||||
|
self.add_action_panel()
|
||||||
|
|
||||||
def add_settings_panel(self, current_content_config: dict, search_type: SearchType, parent_layout: QtWidgets.QLayout):
|
# Set the central widget of the Window. Widget will expand
|
||||||
|
# to take up all the space in the window by default.
|
||||||
|
self.config_window = QtWidgets.QWidget()
|
||||||
|
self.config_window.setLayout(self.layout)
|
||||||
|
self.setCentralWidget(self.config_window)
|
||||||
|
|
||||||
|
|
||||||
|
def add_settings_panel(self, current_content_config: dict, search_type: SearchType):
|
||||||
"Add Settings Panel for specified Search Type. Toggle Editable Search Types"
|
"Add Settings Panel for specified Search Type. Toggle Editable Search Types"
|
||||||
# Get current files from config for given search type
|
# Get current files from config for given search type
|
||||||
if search_type == SearchType.Image:
|
if search_type == SearchType.Image:
|
||||||
@@ -87,11 +94,11 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
# Add setting widgets for given search type to panel
|
# Add setting widgets for given search type to panel
|
||||||
search_type_layout.addWidget(enable_search_type)
|
search_type_layout.addWidget(enable_search_type)
|
||||||
search_type_layout.addWidget(input_files)
|
search_type_layout.addWidget(input_files)
|
||||||
parent_layout.addWidget(search_type_settings)
|
self.layout.addWidget(search_type_settings)
|
||||||
|
|
||||||
return search_type_settings
|
return search_type_settings
|
||||||
|
|
||||||
def add_processor_panel(self, current_conversation_config: dict, processor_type: ProcessorType, parent_layout: QtWidgets.QLayout):
|
def add_processor_panel(self, current_conversation_config: dict, processor_type: ProcessorType):
|
||||||
"Add Conversation Processor Panel"
|
"Add Conversation Processor Panel"
|
||||||
# Get current settings from config for given processor type
|
# Get current settings from config for given processor type
|
||||||
current_openai_api_key = current_conversation_config.get('openai-api-key', None)
|
current_openai_api_key = current_conversation_config.get('openai-api-key', None)
|
||||||
@@ -111,11 +118,11 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
# Add setting widgets for given processor type to panel
|
# Add setting widgets for given processor type to panel
|
||||||
processor_type_layout.addWidget(enable_conversation)
|
processor_type_layout.addWidget(enable_conversation)
|
||||||
processor_type_layout.addWidget(input_field)
|
processor_type_layout.addWidget(input_field)
|
||||||
parent_layout.addWidget(processor_type_settings)
|
self.layout.addWidget(processor_type_settings)
|
||||||
|
|
||||||
return processor_type_settings
|
return processor_type_settings
|
||||||
|
|
||||||
def add_action_panel(self, parent_layout: QtWidgets.QLayout):
|
def add_action_panel(self):
|
||||||
"Add Action Panel"
|
"Add Action Panel"
|
||||||
# Button to Save Settings
|
# Button to Save Settings
|
||||||
action_bar = QtWidgets.QWidget()
|
action_bar = QtWidgets.QWidget()
|
||||||
@@ -127,7 +134,7 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
|
|
||||||
action_bar_layout.addWidget(self.configure_button)
|
action_bar_layout.addWidget(self.configure_button)
|
||||||
action_bar_layout.addWidget(self.search_button)
|
action_bar_layout.addWidget(self.search_button)
|
||||||
parent_layout.addWidget(action_bar)
|
self.layout.addWidget(action_bar)
|
||||||
|
|
||||||
def get_default_config(self, search_type:SearchType=None, processor_type:ProcessorType=None):
|
def get_default_config(self, search_type:SearchType=None, processor_type:ProcessorType=None):
|
||||||
"Get default config"
|
"Get default config"
|
||||||
@@ -139,13 +146,13 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
else:
|
else:
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def add_error_message(self, message: str, parent_layout: QtWidgets.QLayout):
|
def add_error_message(self, message: str):
|
||||||
"Add Error Message to Configure Screen"
|
"Add Error Message to Configure Screen"
|
||||||
error_message = QtWidgets.QLabel()
|
error_message = QtWidgets.QLabel()
|
||||||
error_message.setWordWrap(True)
|
error_message.setWordWrap(True)
|
||||||
error_message.setText(message)
|
error_message.setText(message)
|
||||||
error_message.setStyleSheet("color: red")
|
error_message.setStyleSheet("color: red")
|
||||||
parent_layout.addWidget(error_message)
|
self.layout.addWidget(error_message)
|
||||||
|
|
||||||
def update_search_settings(self):
|
def update_search_settings(self):
|
||||||
"Update config with search settings from UI"
|
"Update config with search settings from UI"
|
||||||
@@ -190,14 +197,14 @@ class ConfigureScreen(QtWidgets.QDialog):
|
|||||||
yaml_utils.parse_config_from_string(self.new_config)
|
yaml_utils.parse_config_from_string(self.new_config)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error validating config: {e}")
|
print(f"Error validating config: {e}")
|
||||||
self.add_error_message(f"Error validating config: {e}", self.layout())
|
self.add_error_message(f"Error validating config: {e}")
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
# Remove error message if present
|
# Remove error message if present
|
||||||
for i in range(self.layout().count()):
|
for i in range(self.layout.count()):
|
||||||
current_widget = self.layout().itemAt(i).widget()
|
current_widget = self.layout.itemAt(i).widget()
|
||||||
if isinstance(current_widget, QtWidgets.QLabel) and current_widget.text().startswith("Error validating config:"):
|
if isinstance(current_widget, QtWidgets.QLabel) and current_widget.text().startswith("Error validating config:"):
|
||||||
self.layout().removeWidget(current_widget)
|
self.layout.removeWidget(current_widget)
|
||||||
current_widget.deleteLater()
|
current_widget.deleteLater()
|
||||||
|
|
||||||
# Save the config to app config file
|
# Save the config to app config file
|
||||||
@@ -8,7 +8,7 @@ from PyQt6 import QtGui, QtWidgets
|
|||||||
from src.utils import constants
|
from src.utils import constants
|
||||||
|
|
||||||
|
|
||||||
def create_system_tray(gui: QtWidgets.QApplication, configure_screen: QtWidgets.QDialog):
|
def create_system_tray(gui: QtWidgets.QApplication, main_window: QtWidgets.QMainWindow):
|
||||||
"""Create System Tray with Menu. Menu contain options to
|
"""Create System Tray with Menu. Menu contain options to
|
||||||
1. Open Search Page on the Web Interface
|
1. Open Search Page on the Web Interface
|
||||||
2. Open App Configuration Screen
|
2. Open App Configuration Screen
|
||||||
@@ -25,7 +25,7 @@ def create_system_tray(gui: QtWidgets.QApplication, configure_screen: QtWidgets.
|
|||||||
menu = QtWidgets.QMenu()
|
menu = QtWidgets.QMenu()
|
||||||
menu_actions = [
|
menu_actions = [
|
||||||
('Search', lambda: webbrowser.open('http://localhost:8000/')),
|
('Search', lambda: webbrowser.open('http://localhost:8000/')),
|
||||||
('Configure', configure_screen.show),
|
('Configure', main_window.show),
|
||||||
('Quit', gui.quit),
|
('Quit', gui.quit),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
12
src/main.py
12
src/main.py
@@ -15,7 +15,7 @@ from src.configure import configure_server
|
|||||||
from src.router import router
|
from src.router import router
|
||||||
from src.utils import constants, state
|
from src.utils import constants, state
|
||||||
from src.utils.cli import cli
|
from src.utils.cli import cli
|
||||||
from src.interface.desktop.configure_screen import ConfigureScreen
|
from src.interface.desktop.main_window import MainWindow
|
||||||
from src.interface.desktop.system_tray import create_system_tray
|
from src.interface.desktop.system_tray import create_system_tray
|
||||||
|
|
||||||
|
|
||||||
@@ -38,24 +38,24 @@ def run():
|
|||||||
else:
|
else:
|
||||||
# Setup GUI
|
# Setup GUI
|
||||||
gui = QtWidgets.QApplication([])
|
gui = QtWidgets.QApplication([])
|
||||||
configure_screen = ConfigureScreen(args.config_file)
|
main_window = MainWindow(args.config_file)
|
||||||
|
|
||||||
# System tray is only available on Windows, MacOS.
|
# System tray is only available on Windows, MacOS.
|
||||||
# On Linux (Gnome) the System tray is not supported.
|
# On Linux (Gnome) the System tray is not supported.
|
||||||
# Since only the Configure Window is available
|
# Since only the Main Window is available
|
||||||
# Quitting it should quit the application
|
# Quitting it should quit the application
|
||||||
if system() in ['Windows', 'Darwin']:
|
if system() in ['Windows', 'Darwin']:
|
||||||
gui.setQuitOnLastWindowClosed(False)
|
gui.setQuitOnLastWindowClosed(False)
|
||||||
tray = create_system_tray(gui, configure_screen)
|
tray = create_system_tray(gui, main_window)
|
||||||
tray.show()
|
tray.show()
|
||||||
|
|
||||||
# Setup Server
|
# Setup Server
|
||||||
configure_server(args, required=False)
|
configure_server(args, required=False)
|
||||||
server = ServerThread(app, args.host, args.port, args.socket)
|
server = ServerThread(app, args.host, args.port, args.socket)
|
||||||
|
|
||||||
# Show Configure Screen on Linux (etc.) or First Run Experience
|
# Show Main Window on First Run Experience or if on Linux
|
||||||
if args.config is None or system() not in ['Windows', 'Darwin']:
|
if args.config is None or system() not in ['Windows', 'Darwin']:
|
||||||
configure_screen.show()
|
main_window.show()
|
||||||
|
|
||||||
# Setup Signal Handlers
|
# Setup Signal Handlers
|
||||||
signal.signal(signal.SIGINT, sigint_handler)
|
signal.signal(signal.SIGINT, sigint_handler)
|
||||||
|
|||||||
Reference in New Issue
Block a user