Singleton that manages pyproject.toml-based plugin packages.
More...
#include <packagemanager.h>
|
| void | packagesInstalled () |
| void | packageInstalled (const QString &packageDir) |
| void | packageInstallFailed (const QString &packageDir, const QString &message) |
| void | featureRegistered (const QString &type, const QString &packageDir, const QString &command, const QString &identifier, const QVariantMap &metadata) |
| void | featureRemoved (const QString &type, const QString &packageDir, const QString &command, const QString &identifier) |
|
|
static PackageManager * | instance () |
| static QStringList | featureTypes () |
| static QString | featureSettingsKey (const QString &packageDir, const QString &command, const QString &identifier) |
| static QString | packageFeatureKey (const QString &packageDir, const QString &command, const QString &identifier) |
| static QJsonObject | loadOptionsFromFile (const QString &userOptionsPath) |
| static void | mergeOptionsFromFile (QJsonObject &opts, const QString &userOptionsPath) |
| static QString | packageVersion (const QString &packageDir) |
| static bool | hasPixiManifest (const QString &packageDir) |
| static QString | pixiScriptPath (const QString &packageDir, const QString &command) |
| static QString | venvScriptPath (const QString &packageDir, const QString &command) |
| static CommandLine | resolveCommandLine (const QString &packageDir, const QString &command) |
| static CommandLine | resolveCommandLine (const QString &packageDir, const QString &command, const QString &pixiExecutable) |
| static QJsonObject | loadOptionsFromScript (const QString &packageDir, const QString &command, const QString &identifier) |
| static bool | isDynamicUserOptions (const QString &userOptionsValue) |
| static QJsonObject | resolveUserOptions (const QString &userOptionsValue, const QString &packageDir, const QString &command, const QString &identifier) |
| static bool | removeSupersededVenv (const QString &packageDir, const QString &command) |
| static void | clearInstallFailure (const QString &packageDir) |
Packages are registered once (at download time or manually) and cached in QSettings. On startup, loadRegisteredPackages() replays the cached registrations as featureRegistered() signals so that consumer plugins (Command, ScriptCharges, Forcefield, etc.) can create their actions and models without re-parsing TOML or calling scripts.
During a session, registerPackage() can be called at any time (e.g. after the plugin downloader installs a new package) and signals fire immediately.
◆ featureTypes()
| QStringList featureTypes |
( |
| ) |
|
|
static |
Known feature-type strings (TOML table names under [tool.avogadro]).
◆ featureSettingsKey()
| QString featureSettingsKey |
( |
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | identifier ) |
|
static |
A short, readable, stable key naming one feature, for use as a QSettings group. Unlike packageFeatureKey() this embeds no absolute path, so it does not turn into a deep tree of settings groups.
◆ packageFeatureKey()
| QString packageFeatureKey |
( |
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | identifier ) |
|
static |
Build a stable key for one package-provided feature. Consumers can use this as a map key to track registrations and removals. Components must not be empty.
◆ loadOptionsFromFile()
| QJsonObject loadOptionsFromFile |
( |
const QString & | userOptionsPath | ) |
|
|
static |
Load package user-options from JSON or TOML (selected by extension). Returns an empty object on error.
◆ mergeOptionsFromFile()
| void mergeOptionsFromFile |
( |
QJsonObject & | opts, |
|
|
const QString & | userOptionsPath ) |
|
static |
Merge package user-options into opts. Keys from the file override existing values in opts.
◆ packageVersion()
| QString packageVersion |
( |
const QString & | packageDir | ) |
|
|
static |
The [project.version] declared by the pyproject.toml in packageDir, or an empty string if it cannot be read.
◆ hasPixiManifest()
| bool hasPixiManifest |
( |
const QString & | packageDir | ) |
|
|
static |
Whether packageDir declares a pixi workspace of its own: a pixi.toml, or a pyproject.toml with a non-empty [tool.pixi] table.
pixi finds its manifest by walking up from the directory it is run in, so a package that declares none is not merely unsupported — pixi silently operates on an ancestor's workspace instead. "pixi install" then reports success having installed something else entirely, and the package's own command is nowhere on PATH ("command not found", exit 127). Such a package has to be installed with pip into .venv.
◆ pixiScriptPath()
| QString pixiScriptPath |
( |
const QString & | packageDir, |
|
|
const QString & | command ) |
|
static |
Absolute path to command as installed in the pixi environment of packageDir (.pixi/envs/default), or an empty string if the package has no pixi environment with that command in it.
Package commands are run with "pixi run –as-is", which is shorthand for --no-install --frozen and so will never create a missing environment. Callers must therefore check this rather than merely checking that the pixi executable exists.
◆ venvScriptPath()
| QString venvScriptPath |
( |
const QString & | packageDir, |
|
|
const QString & | command ) |
|
static |
Absolute path to command as installed in the virtual environment of packageDir (.venv), or an empty string if there is none. This is the fallback for packages that were pip-installed because pixi was not available when they were set up.
◆ resolveCommandLine() [1/2]
| CommandLine resolveCommandLine |
( |
const QString & | packageDir, |
|
|
const QString & | command ) |
|
static |
Resolve how to run command from packageDir, so that every caller applies the same backend policy.
In order of preference:
"pixi run –as-is" when the pixi executable is found and the pixi environment provides command;
- the pixi environment's own script, run directly, when pixi cannot be found (for example an application launched from the Finder or Dock has no Homebrew directory on its PATH) – the script works without pixi, but skips activation, hence CommandLine::environmentBinDir;
- the console script pip installed into
.venv.
Having the pixi executable is not on its own enough to choose pixi, because "pixi run –as-is" is shorthand for --no-install --frozen and will not create a missing environment: a package installed before pixi was available has to keep running from .venv until it is installed again.
- Returns
- a CommandLine whose
program is empty when neither environment provides command.
◆ resolveCommandLine() [2/2]
| CommandLine resolveCommandLine |
( |
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | pixiExecutable ) |
|
static |
As above, but with the pixi executable supplied by the caller rather than searched for. pixiExecutable may be empty, meaning "pixi not found".
◆ loadOptionsFromScript()
| QJsonObject loadOptionsFromScript |
( |
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | identifier ) |
|
static |
Run the package script with --user-options and parse the JSON output. Uses pixi (preferred) or the venv-installed script as fallback. Returns an empty object on error.
◆ isDynamicUserOptions()
| bool isDynamicUserOptions |
( |
const QString & | userOptionsValue | ) |
|
|
static |
Whether a feature's user-options value asks for options to be built fresh by the script rather than read from a file. Such options are generated per invocation, so callers must not cache the resulting GUI.
◆ resolveUserOptions()
| QJsonObject resolveUserOptions |
( |
const QString & | userOptionsValue, |
|
|
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | identifier ) |
|
static |
◆ installPackages()
| void installPackages |
( |
const QStringList & | packageDirs | ) |
|
Asynchronously run pixi (preferred) or pip install in each directory, then call registerPackage() for each package that installed. Emits packageInstalled() or packageInstallFailed() for each package, then packagesInstalled() when the background thread finishes. A failure is remembered (see scanDirectory()) and the package is not registered; a previously registered package is kept only while one of its environments can still run its command. Safe to call from the main thread.
◆ removeSupersededVenv()
| bool removeSupersededVenv |
( |
const QString & | packageDir, |
|
|
const QString & | command ) |
|
static |
Delete the .venv directory of packageDir once its pixi environment can run command, so that a package migrated to pixi does not keep a stale pip-installed tree around. Nothing will ever update that tree, and it would silently serve outdated code if the pixi environment were later removed.
Does nothing if there is no .venv, or if the pixi environment does not provide command — a half-finished install must never leave the package with no way to run at all.
- Returns
- true if a
.venv directory was removed.
◆ clearInstallFailure()
| void clearInstallFailure |
( |
const QString & | packageDir | ) |
|
|
static |
Forget recorded install failures for packageDir, so that scanDirectory() offers it again.
◆ registerPackage()
| bool registerPackage |
( |
const QString & | packageDir | ) |
|
Parse pyproject.toml in packageDir, cache the result in QSettings, and emit featureRegistered() for every feature found.
- Returns
- true on success.
◆ unregisterPackage()
| bool unregisterPackage |
( |
const QString & | packageName | ) |
|
Remove a package and all its feature registrations from the cache. Emits featureRemoved() for each feature that was registered.
◆ loadRegisteredPackages()
| void loadRegisteredPackages |
( |
const QString & | typeFilter = QString() | ) |
|
Load all previously-registered packages from QSettings and emit featureRegistered() for each cached feature. Call this once after all consumer plugins have connected.
◆ scanDirectory()
| QStringList scanDirectory |
( |
const QString & | directoryPath | ) |
|
Scan directoryPath for subdirectories that contain a pyproject.toml. Each discovered package is compared against the cached hash of its pyproject.toml; new or modified packages are returned as a list of absolute directory paths. The caller is responsible for calling registerPackage() on any directories it wants to install. A package whose install already failed for the current pyproject.toml is not returned again until that file changes; likewise pixi is not retried for a package that pip-installed after pixi failed.
- Returns
- list of package directories that are new or have been modified.
◆ packageFeatureTypes()
| QStringList packageFeatureTypes |
( |
const QString & | packageName | ) |
const |
Return the distinct feature-type strings (e.g. "menu-commands", "file-formats") for a registered package, read from the QSettings cache.
◆ packagesInstalled
| void packagesInstalled |
( |
| ) |
|
|
signal |
◆ packageInstalled
| void packageInstalled |
( |
const QString & | packageDir | ) |
|
|
signal |
◆ packageInstallFailed
| void packageInstallFailed |
( |
const QString & | packageDir, |
|
|
const QString & | message ) |
|
signal |
Emitted for each package installPackages() could not install.
- Parameters
-
| message | Which backend(s) failed and the tail of their stderr. |
◆ featureRegistered
| void featureRegistered |
( |
const QString & | type, |
|
|
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | identifier, |
|
|
const QVariantMap & | metadata ) |
|
signal |
Emitted for each feature found in a package.
- Parameters
-
| type | One of the featureTypes() strings, e.g. "menu-commands", "electrostatic-models", etc. |
| packageDir | Absolute path to the package directory. |
| command | Entry-point name from [project.scripts]. |
| identifier | The feature's unique identifier. |
| metadata | Remaining TOML sub-table fields as a QVariantMap. |
◆ featureRemoved
| void featureRemoved |
( |
const QString & | type, |
|
|
const QString & | packageDir, |
|
|
const QString & | command, |
|
|
const QString & | identifier ) |
|
signal |
Emitted when a feature is removed (so consumers can clean up).
- Parameters
-
| type | One of the featureTypes() strings. |
| packageDir | Absolute path to the package directory. |
| command | Entry-point name from [project.scripts]. |
| identifier | The feature's unique identifier. |
The documentation for this class was generated from the following file: