Skip to content

Conversation

@pcortellezzi
Copy link
Contributor

Overview

This PR refactors how Launcher plugins are handled to support state persistence and asynchronous UI updates. Previously, Launcher plugins were instantiated and destroyed for every single query, preventing them from maintaining internal state or performing async tasks.

Concrete Example: The Qalculate Plugin

This refactoring was driven by the needs of advanced plugins like Qalculate.

  • Persistence: The plugin keeps a background qalc process alive for instant performance. Without this PR, the process would be killed and restarted at every keystroke.
  • Asynchronicity: When a calculation is sent, the plugin can now immediately return a "Calculating..." item and then signal the UI to refresh with the final result once the background process responds, without freezing or blocking the launcher.

Key Changes

  1. Persistent Launcher Instances:

    • Launcher plugins are now instantiated upon loading and stored in PluginService.pluginInstances, similar to Daemons.
    • This allows plugins to maintain a background state (e.g., a long-running process or an active connection).
  2. Asynchronous UI Updates:

    • Introduced a requestLauncherUpdate(pluginId) signal in PluginService.
    • AppLauncher now listens to this signal to trigger a refresh. Plugins can now update the items list at any time, not just during the initial query.
  3. AppSearchService Optimization:

    • AppSearchService now reuses the persistent instance from PluginService.
    • It maintains backward compatibility by falling back to the old create/destroy behavior if no persistent instance is found.
  4. Dependency Injection:

    • The PluginService singleton is injected into plugins during creation (pluginService: root), enabling easier access to shared services and data.

Why this is needed

This architecture is essential for any plugin that interacts with external binaries, APIs, or performs heavy computations. It makes the launcher capable of handling non-instant results while remaining fluid for the user.

- PluginService: maintain persistent instances for Launcher plugins
- AppSearchService: reuse persistent instances for queries
- Added requestLauncherUpdate signal for async UI refreshes
@bbedward
Copy link
Collaborator

bbedward commented Jan 2, 2026

Great thank you, I'll get a chance to review this later. But you should refactor your qalculate plugin to use QtObject and PluginSettings, I made PRs to existing launcher plugins for the same (like DankCalculator)

@pcortellezzi
Copy link
Contributor Author

Thanks for the suggestion! 🙂 I've refactored both the Qalculate and Powermenu plugins to use QtObject and PluginSettings following your advice, thanks!

@bbedward bbedward merged commit d2c4391 into AvengeMedia:master Jan 2, 2026
1 check passed
ewtodd pushed a commit to ewtodd/DankMaterialShell that referenced this pull request Jan 2, 2026
- PluginService: maintain persistent instances for Launcher plugins
- AppSearchService: reuse persistent instances for queries
- Added requestLauncherUpdate signal for async UI refreshes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants