moment/harmonyqml/engine.py

73 lines
2.3 KiB
Python
Raw Normal View History

# Copyright 2019 miruka
# This file is part of harmonyqml, licensed under GPLv3.
import logging
import sys
from pathlib import Path
from typing import Generator, Optional
from PyQt5.QtCore import QFileSystemWatcher, QObject, QTimer
from PyQt5.QtQml import QQmlApplicationEngine
from .__about__ import __doc__
from .app import Application
from .backend.backend import Backend
# logging.basicConfig(level=logging.INFO)
class Engine(QQmlApplicationEngine):
def __init__(self,
app: Application,
debug: bool = False,
parent: Optional[QObject] = None) -> None:
super().__init__(parent)
self.app = app
self.backend = Backend()
self.app_dir = Path(sys.argv[0]).resolve().parent
# Set QML properties
self.rootContext().setContextProperty("Engine", self)
self.rootContext().setContextProperty("Backend", self.backend)
# Connect Qt signals
self.quit.connect(self.app.quit)
# Make SIGINT (ctrl-c) work
self._sigint_timer = QTimer()
self._sigint_timer.timeout.connect(lambda: None)
self._sigint_timer.start(100)
# Setup UI live-reloading when a file is edited
if debug:
self._watcher = QFileSystemWatcher()
self._watcher.directoryChanged.connect(lambda _: self.reload_qml())
self._watcher.addPath(str(self.app_dir))
for _dir in list(self._recursive_dirs_in(self.app_dir)):
self._watcher.addPath(str(_dir))
# Load QML page and show window
self.load(str(self.app_dir / "components" / "Window.qml"))
def show_window(self) -> None:
self.rootObjects()[0].show()
sys.exit(self.app.exec())
def _recursive_dirs_in(self, path: Path) -> Generator[Path, None, None]:
for item in path.iterdir():
if item.is_dir() and item.name != "__pycache__":
yield item
yield from self._recursive_dirs_in(item)
def reload_qml(self) -> None:
self.clearComponentCache()
loader = self.rootObjects()[0].findChild(QObject, "UILoader")
source = loader.property("source")
loader.setProperty("source", None)
loader.setProperty("source", source)
logging.info("Reloaded: %s", source)