Update Desktop Interface to Handle No System Tray on Linux

- What
  - Add Button to Open Search Interface on Web in "Configure Screen"
    - Provides GUI affordance for opening search interface to Linux users
  - On Linux
    - Show Configure Screen, even if not first run experience
    - Do no show system tray on Linux
    - Quit app on closing Configure Screen
  - On Windows, Mac
    - Show Configure screen only if first run experience
    - Show system tray always
    - Do not quit app on closing Configure Screen
- Why
  - Configure screen is the only GUI element on Linux. So closing it
    should close the application
  - On Windows, Mac the system tray exists, so app should not be closed
    on closing configure screen
This commit is contained in:
Debanjum 2022-08-13 01:06:07 +03:00 committed by GitHub
commit a6b2190f7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 14 deletions

View file

@ -1,6 +1,7 @@
# Standard Packages # Standard Packages
from pathlib import Path from pathlib import Path
from copy import deepcopy from copy import deepcopy
import webbrowser
# External Packages # External Packages
@ -31,14 +32,16 @@ class ConfigureScreen(QtWidgets.QDialog):
# Load config from existing config, if exists, else load from default config # Load config from existing config, if exists, else load from default config
if resolve_absolute_path(self.config_file).exists(): if resolve_absolute_path(self.config_file).exists():
self.first_run = False
self.current_config = yaml_utils.load_config_from_file(self.config_file) self.current_config = yaml_utils.load_config_from_file(self.config_file)
else: else:
self.first_run = True
self.current_config = deepcopy(constants.default_config) self.current_config = deepcopy(constants.default_config)
self.new_config = self.current_config self.new_config = self.current_config
# Initialize Configure Window # Initialize Configure Window
self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint) self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint)
self.setWindowTitle("Configure - Khoj") self.setWindowTitle("Khoj")
self.setFixedWidth(600) self.setFixedWidth(600)
# Initialize Configure Window Layout # Initialize Configure Window Layout
@ -118,9 +121,12 @@ class ConfigureScreen(QtWidgets.QDialog):
action_bar = QtWidgets.QWidget() action_bar = QtWidgets.QWidget()
action_bar_layout = QtWidgets.QHBoxLayout(action_bar) action_bar_layout = QtWidgets.QHBoxLayout(action_bar)
self.save_button = QtWidgets.QPushButton("Start", clicked=self.save_settings) self.configure_button = QtWidgets.QPushButton("Configure", clicked=self.configure_app)
self.search_button = QtWidgets.QPushButton("Search", clicked=lambda: webbrowser.open('http://localhost:8000/'))
self.search_button.setEnabled(not self.first_run)
action_bar_layout.addWidget(self.save_button) action_bar_layout.addWidget(self.configure_button)
action_bar_layout.addWidget(self.search_button)
parent_layout.addWidget(action_bar) parent_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):
@ -207,12 +213,12 @@ class ConfigureScreen(QtWidgets.QDialog):
# Configure server with loaded config # Configure server with loaded config
configure_server(args, required=True) configure_server(args, required=True)
def save_settings(self): def configure_app(self):
"Save the new settings to khoj.yml. Reload app with updated settings" "Save the new settings to khoj.yml. Reload app with updated settings"
self.update_search_settings() self.update_search_settings()
self.update_processor_settings() self.update_processor_settings()
if self.save_settings_to_file(): if self.save_settings_to_file():
# Setup thread # Setup thread to load updated settings in background
self.thread = QThread() self.thread = QThread()
self.settings_loader = SettingsLoader(self.load_updated_settings) self.settings_loader = SettingsLoader(self.load_updated_settings)
self.settings_loader.moveToThread(self.thread) self.settings_loader.moveToThread(self.thread)
@ -227,12 +233,14 @@ class ConfigureScreen(QtWidgets.QDialog):
self.thread.start() self.thread.start()
# Disable Save Button # Disable Save Button
self.save_button.setEnabled(False) self.search_button.setEnabled(False)
self.save_button.setText("Saving...") self.configure_button.setEnabled(False)
self.configure_button.setText("Configuring...")
# Reset UI # Reset UI
self.thread.finished.connect(lambda: self.save_button.setText("Start")) self.thread.finished.connect(lambda: self.configure_button.setText("Configure"))
self.thread.finished.connect(lambda: self.save_button.setEnabled(True)) self.thread.finished.connect(lambda: self.configure_button.setEnabled(True))
self.thread.finished.connect(lambda: self.search_button.setEnabled(True))
class SettingsLoader(QObject): class SettingsLoader(QObject):

View file

@ -1,4 +1,5 @@
# Standard Packages # Standard Packages
from platform import system
import signal import signal
import sys import sys
@ -37,17 +38,23 @@ def run():
else: else:
# Setup GUI # Setup GUI
gui = QtWidgets.QApplication([]) gui = QtWidgets.QApplication([])
gui.setQuitOnLastWindowClosed(False)
configure_screen = ConfigureScreen(args.config_file) configure_screen = ConfigureScreen(args.config_file)
tray = create_system_tray(gui, configure_screen)
tray.show() # System tray is only available on Windows, MacOS.
# On Linux (Gnome) the System tray is not supported.
# Since only the Configure Window is available
# Quitting it should quit the application
if system() in ['Windows', 'Darwin']:
gui.setQuitOnLastWindowClosed(False)
tray = create_system_tray(gui, configure_screen)
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)
# Trigger First Run Experience, if required # Show Configure Screen on Linux (etc.) or First Run Experience
if args.config is None: if args.config is None or system() not in ['Windows', 'Darwin']:
configure_screen.show() configure_screen.show()
# Setup Signal Handlers # Setup Signal Handlers