Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions src/core/widgets/services/quick_launch/providers/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def _get_lnk_description(lnk_path: str) -> str | None:
class DescriptionResolverWorker(QThread):
"""Background thread to resolve app descriptions."""

finished = pyqtSignal(dict)
descriptions_ready = pyqtSignal(dict)

def __init__(self, apps: list[AppEntry]):
super().__init__()
Expand Down Expand Up @@ -218,7 +218,7 @@ def run(self):
cache[path] = _get_lnk_description(path) or path
elif os.path.isfile(path):
cache[path] = _get_exe_description(path) or path
self.finished.emit(cache)
self.descriptions_ready.emit(cache)


def _is_subfolder_app(path: str) -> bool:
Expand All @@ -245,6 +245,8 @@ def __init__(self, config: dict[str, Any] | None = None):
self._history = LaunchHistory()
self._desc_cache: dict[str, str] = {}
self._desc_worker: DescriptionResolverWorker | None = None
self._desc_apps: list[AppEntry] | None = None
self._pending_desc_apps: list[AppEntry] | None = None

@property
def service(self) -> QuickLaunchService:
Expand All @@ -259,15 +261,32 @@ def match(self, text: str) -> bool:

def start_description_resolution(self, apps: list[AppEntry]):
"""Start background thread to resolve app descriptions."""
if self._desc_worker and self._desc_worker.isRunning():
self._desc_worker.finished.disconnect()
self._desc_worker.wait()
self._desc_worker = DescriptionResolverWorker(apps)
self._desc_worker.finished.connect(self._on_descriptions_ready)
if apps == self._desc_apps:
self._pending_desc_apps = None
return
if self._desc_worker is not None:
self._pending_desc_apps = list(apps)
return
self._desc_apps = list(apps)
self._desc_worker = DescriptionResolverWorker(self._desc_apps)
self._desc_worker.descriptions_ready.connect(self._on_descriptions_ready)
self._desc_worker.finished.connect(self._on_description_worker_finished)
self._desc_worker.start()

def _on_descriptions_ready(self, cache: dict[str, str]):
self._desc_cache = cache
if self.request_refresh:
self.request_refresh()

def _on_description_worker_finished(self):
worker = self._desc_worker
self._desc_worker = None
if worker is not None:
worker.deleteLater()
pending = self._pending_desc_apps
self._pending_desc_apps = None
if pending is not None:
self.start_description_resolution(pending)

def get_results(self, text: str, **kwargs: Any) -> list[ProviderResult]:
svc = self.service
Expand Down
21 changes: 19 additions & 2 deletions src/core/widgets/services/quick_launch/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def __init__(self):
self._show_icons: bool = True

self._app_loader: AppListLoader | None = None
self._app_reload_pending = False
self._query_worker = QueryWorker()
self._query_worker.finished.connect(self._on_query_finished)
self._query_worker.start()
Expand Down Expand Up @@ -142,6 +143,8 @@ def configure_providers(
if not self._apps_loaded and not self._app_loader:
self._setup_fs_watcher()
self._start_app_loading()
elif self._apps_loaded:
self._start_description_resolution()

def async_query(self, text: str, max_results: int = 50) -> str:
"""Submit an async query. Returns a query_id to match results."""
Expand All @@ -154,13 +157,27 @@ def _on_query_finished(self, query_id: str, results: list[ProviderResult]):
self.query_finished.emit(query_id, results)

def _start_app_loading(self):
if self._app_loader:
self._app_loader.apps_loaded.disconnect(self._on_apps_loaded)
if self._app_loader is not None:
self._app_reload_pending = True
return
self._app_loader = AppListLoader()
self._app_loader.apps_loaded.connect(self._on_apps_loaded)
self._app_loader.finished.connect(self._on_app_loading_finished)
self._app_loader.start()

def _on_app_loading_finished(self):
loader = self._app_loader
self._app_loader = None
if loader is not None:
loader.deleteLater()
if self._app_reload_pending:
self._app_reload_pending = False
AppListLoader.clear_cache()
self._start_app_loading()

def _on_apps_loaded(self, apps: list[AppEntry]):
if self._apps_loaded and apps == self._apps:
return
self._apps = apps
self._apps_loaded = True
if self._show_icons:
Expand Down