Remove PySide dependency and deprecate desktop builds (#475)

* Remove PySide, gui option from code
* Remove pyside 6 dependency from code
* Remove workflows which build desktop applications
* Update unit tests and update line in documentation
* Remove additional references to pyinstaller, gui
* Add uninstall steps to normal uninstall instructions
This commit is contained in:
sabaimran
2023-09-07 11:36:27 -07:00
committed by GitHub
parent 76562f4250
commit dccfae3853
14 changed files with 13 additions and 568 deletions

View File

@@ -1,75 +0,0 @@
# Standard Packages
import webbrowser
import os
import signal
# External Packages
from PySide6 import QtGui, QtWidgets
from PySide6.QtCore import Qt
# Internal Packages
from khoj.utils import constants
from PySide6.QtCore import QThread
class ServerThread(QThread):
def __init__(self, start_server_func, parent=None):
super(ServerThread, self).__init__(parent)
self.start_server_func = start_server_func
def __del__(self):
self.wait()
def run(self):
self.start_server_func()
def exit(self):
os.kill(os.getpid(), signal.SIGTERM)
super(ServerThread, self).exit()
class MainWindow(QtWidgets.QMainWindow):
"""Create Window to Navigate users to the web UI"""
def __init__(self, host: str, port: int):
super(MainWindow, self).__init__()
# Initialize Configure Window
self.setWindowTitle("Khoj")
# Set Window Icon
icon_path = constants.web_directory / "assets/icons/favicon-128x128.png"
self.setWindowIcon(QtGui.QIcon(f"{icon_path.absolute()}"))
# Initialize Configure Window Layout
self.wlayout = QtWidgets.QVBoxLayout()
# Add a Label that says "Khoj Configuration" to the Window
self.wlayout.addWidget(QtWidgets.QLabel("Welcome to Khoj"))
# Add a Button to open the Web UI at http://host:port/config
self.open_web_ui_button = QtWidgets.QPushButton("Open Web UI")
self.open_web_ui_button.clicked.connect(lambda: webbrowser.open(f"http://{host}:{port}/config"))
self.wlayout.addWidget(self.open_web_ui_button)
# 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.wlayout)
self.setCentralWidget(self.config_window)
self.position_window()
def position_window(self):
"Position the window at center of X axis and near top on Y axis"
window_rectangle = self.geometry()
screen_center = self.screen().availableGeometry().center()
window_rectangle.moveCenter(screen_center)
self.move(window_rectangle.topLeft().x(), 25)
def show_on_top(self):
"Bring Window on Top"
self.show()
self.setWindowState(Qt.WindowState.WindowActive)
self.activateWindow() # For Bringing to Top on Windows
self.raise_() # For Bringing to Top from Minimized State on OSX

View File

@@ -1,43 +0,0 @@
# Standard Packages
import webbrowser
# External Packages
from PySide6 import QtGui, QtWidgets
# Internal Packages
from khoj.utils import constants, state
from khoj.interface.desktop.main_window import MainWindow
def create_system_tray(gui: QtWidgets.QApplication, main_window: MainWindow):
"""Create System Tray with Menu. Menu contain options to
1. Open Search Page on the Web Interface
2. Open App Configuration Screen
3. Quit Application
"""
# Create the system tray with icon
icon_path = constants.web_directory / "assets/icons/favicon-128x128.png"
icon = QtGui.QIcon(f"{icon_path.absolute()}")
tray = QtWidgets.QSystemTrayIcon(icon)
tray.setVisible(True)
# Create the menu and menu actions
menu = QtWidgets.QMenu()
menu_actions = [
("Search", lambda: webbrowser.open(f"http://{state.host}:{state.port}/")),
("Configure", lambda: webbrowser.open(f"http://{state.host}:{state.port}/config")),
("App", main_window.show),
("Quit", gui.quit),
]
# Add the menu actions to the menu
for action_text, action_function in menu_actions:
menu_action = QtGui.QAction(action_text, menu)
menu_action.triggered.connect(action_function) # type: ignore[attr-defined]
menu.addAction(menu_action)
# Add the menu to the system tray
tray.setContextMenu(menu)
return tray

View File

@@ -1,6 +1,5 @@
# Standard Packages
import os
import signal
import sys
import locale
@@ -12,8 +11,6 @@ if sys.stderr is None:
import logging
import threading
import warnings
from platform import system
import webbrowser
from importlib.metadata import version
# Ignore non-actionable warnings
@@ -70,81 +67,13 @@ def run():
logger.info("🌘 Starting Khoj")
if not args.gui:
# Setup task scheduler
poll_task_scheduler()
# Setup task scheduler
poll_task_scheduler()
# Start Server
configure_routes(app)
initialize_server(args.config, required=False)
start_server(app, host=args.host, port=args.port, socket=args.socket)
else:
from PySide6 import QtWidgets
from PySide6.QtCore import QTimer
from khoj.interface.desktop.main_window import MainWindow, ServerThread
from khoj.interface.desktop.system_tray import create_system_tray
# Setup GUI
gui = QtWidgets.QApplication([])
main_window = MainWindow(args.host, args.port)
# System tray is only available on Windows, MacOS.
# On Linux (Gnome) the System tray is not supported.
# Since only the Main Window is available
# Quitting it should quit the application
if system() in ["Windows", "Darwin"]:
gui.setQuitOnLastWindowClosed(False)
tray = create_system_tray(gui, main_window)
tray.show()
# Setup Server
initialize_server(args.config, required=False)
configure_routes(app)
server = ServerThread(start_server_func=lambda: start_server(app, host=args.host, port=args.port), parent=gui)
url = f"http://{args.host}:{args.port}"
logger.info(f"🌗 Khoj is running at {url}")
try:
startup_url = url if args.config else f"{url}/config"
webbrowser.open(startup_url)
except:
logger.warning(f"🚧 Unable to open browser. Please open {url} manually to configure or use Khoj.")
# Show Main Window on First Run Experience or if on Linux
if args.config is None or system() not in ["Windows", "Darwin"]:
main_window.show()
# Setup Signal Handlers
signal.signal(signal.SIGINT, sigint_handler)
# Invoke Python interpreter every 500ms to handle signals, run scheduled tasks
timer = QTimer()
timer.start(500)
timer.timeout.connect(schedule.run_pending)
# Start Application
server.start()
gui.aboutToQuit.connect(server.exit)
# Close Splash Screen if still open
if system() != "Darwin":
try:
import pyi_splash
# Update the text on the splash screen
pyi_splash.update_text("Khoj setup complete")
# Close Splash Screen
pyi_splash.close()
except:
pass
gui.exec()
def sigint_handler(*args):
from PySide6 import QtWidgets
QtWidgets.QApplication.quit()
# Start Server
configure_routes(app)
initialize_server(args.config, required=False)
start_server(app, host=args.host, port=args.port, socket=args.socket)
def set_state(args):
@@ -171,12 +100,3 @@ def poll_task_scheduler():
timer_thread.daemon = True
timer_thread.start()
schedule.run_pending()
def run_gui():
sys.argv += ["--gui"]
run()
if __name__ == "__main__":
run_gui()

View File

@@ -17,7 +17,6 @@ def cli(args=None):
parser.add_argument(
"--config-file", "-c", default="~/.khoj/khoj.yml", type=pathlib.Path, help="YAML file to configure Khoj"
)
parser.add_argument("--gui", action="store_true", default=False, help="Show native desktop GUI. Default: false")
parser.add_argument(
"--regenerate",
action="store_true",

View File

@@ -106,11 +106,6 @@ def load_model(
return model
def is_pyinstaller_app():
"Returns true if the app is running from Native GUI created by PyInstaller"
return getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")
def get_class_by_name(name: str) -> object:
"Returns the class object from name string"
module_name, class_name = name.rsplit(".", 1)