diff --git a/src/core/widgets/services/quick_launch/providers/apps.py b/src/core/widgets/services/quick_launch/providers/apps.py index 38bdd3bb5..fb7060d73 100644 --- a/src/core/widgets/services/quick_launch/providers/apps.py +++ b/src/core/widgets/services/quick_launch/providers/apps.py @@ -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__() @@ -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: @@ -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: @@ -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 diff --git a/src/core/widgets/services/quick_launch/service.py b/src/core/widgets/services/quick_launch/service.py index d745343a6..b968f39c4 100644 --- a/src/core/widgets/services/quick_launch/service.py +++ b/src/core/widgets/services/quick_launch/service.py @@ -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() @@ -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.""" @@ -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: