Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
PhosphorTiles::ScriptedAlgorithmLoader Class Reference

Discovers, loads, and hot-reloads LuauTileAlgorithm instances. More...

#include <phosphor-tiles/include/PhosphorTiles/ScriptedAlgorithmLoader.h>

Inheritance diagram for PhosphorTiles::ScriptedAlgorithmLoader:
[legend]

Signals

void algorithmsChanged ()
 Emitted after any add/remove/reload of scripted algorithms.
 

Public Member Functions

 ScriptedAlgorithmLoader (const QString &subdirectory, ITileAlgorithmRegistry *registry, QObject *parent=nullptr)
 Construct a loader for subdirectory under XDG data dirs.
 
 ~ScriptedAlgorithmLoader () override
 
void scanAndRegister (PhosphorFsLoader::LiveReload liveReload=PhosphorFsLoader::LiveReload::On)
 Discover and load all .luau algorithms from system + user dirs.
 
void ensureUserDirectoryExists ()
 Create the user algorithm directory if it does not exist.
 
QString userAlgorithmDir () const
 Writable user directory path for custom algorithms.
 

Static Public Attributes

static constexpr int MaxWatchedFilesPerDir = 100
 Per-directory cap on .luau files considered by one scan.
 
static constexpr int MaxScripts = 10'000
 Hard cap on scripts REGISTERED per rescan, summed across every registered directory.
 

Detailed Description

Discovers, loads, and hot-reloads LuauTileAlgorithm instances.

Scans system and user algorithm directories for .luau files, creates LuauTileAlgorithm instances, and registers them with the injected ITileAlgorithmRegistry. Watches directories and files via QFileSystemWatcher with debounced refresh so that new/modified/ deleted scripts are picked up automatically.

The application injects the subdirectory name (relative to QStandardPaths::GenericDataLocation) at construction — the library is brand-agnostic. For Phosphor this is "plasmazones/algorithms".

User scripts under writableLocation/<subdirectory>/ override system scripts declaring the same script ID (which defaults to script:<basename> but is overridden by the script's own id metadata, so it is not simply the filename). System dirs come from every XDG GenericDataLocation entry, in order. A script may only ever shadow another script by that XDG priority, never a C++ built-in: a script whose id collides with a built-in is refused outright.

Constructor & Destructor Documentation

◆ ScriptedAlgorithmLoader()

PhosphorTiles::ScriptedAlgorithmLoader::ScriptedAlgorithmLoader ( const QString &  subdirectory,
ITileAlgorithmRegistry registry,
QObject *  parent = nullptr 
)
explicit

Construct a loader for subdirectory under XDG data dirs.

subdirectory is a relative path (no leading slash) appended to every QStandardPaths::GenericDataLocation entry. Pass the empty string to disable all discovery (the loader becomes a no-op).

registry is the tile-algorithm registry the loader registers discovered scripts against. Caller owns registry and must keep it alive for the loader's lifetime.

◆ ~ScriptedAlgorithmLoader()

PhosphorTiles::ScriptedAlgorithmLoader::~ScriptedAlgorithmLoader ( )
override

Member Function Documentation

◆ algorithmsChanged

void PhosphorTiles::ScriptedAlgorithmLoader::algorithmsChanged ( )
signal

Emitted after any add/remove/reload of scripted algorithms.

◆ ensureUserDirectoryExists()

void PhosphorTiles::ScriptedAlgorithmLoader::ensureUserDirectoryExists ( )

Create the user algorithm directory if it does not exist.

◆ scanAndRegister()

void PhosphorTiles::ScriptedAlgorithmLoader::scanAndRegister ( PhosphorFsLoader::LiveReload  liveReload = PhosphorFsLoader::LiveReload::On)

Discover and load all .luau algorithms from system + user dirs.

Rescans every algorithm directory and diffs the result against the previous scan: unchanged files keep their existing registry entry, new and edited ones are (re)built, and entries whose file disappeared are unregistered. No registry entry is dropped up front — the loader's own tracking maps are rebuilt from scratch each scan and the stale sweep runs at the end.

Directories are iterated USER-FIRST with first-registration-wins on script ID, which is what produces user > sys-highest > … > sys-lowest. (The list handed in is system-first; performScan reverse-iterates it.)

liveReload defaults to On so production callers (daemon, editor, settings) get hot-reload by default. Pass Off from tests / batch-import contexts that want a one-shot scan with no background watcher attached. The flag is forwarded to the underlying WatchedDirectorySet and inherits its one-way-enable semantics: once any call passes On, the watcher stays armed for the loader's lifetime.

Idempotent on the registry: a re-scan that resolves to an empty directory set still drives the diff path so previously-registered scripts get unregistered as stale.

Change-detection is observable via the algorithmsChanged signal, which fires from inside the strategy when the on-disk script set differs from the previous scan's signature.

◆ userAlgorithmDir()

QString PhosphorTiles::ScriptedAlgorithmLoader::userAlgorithmDir ( ) const

Writable user directory path for custom algorithms.

Returns
Absolute path to the configured subdirectory under QStandardPaths::writableLocation(GenericDataLocation), or empty string if the subdirectory was empty.

Member Data Documentation

◆ MaxScripts

constexpr int PhosphorTiles::ScriptedAlgorithmLoader::MaxScripts = 10'000
staticconstexpr

Hard cap on scripts REGISTERED per rescan, summed across every registered directory.

Header-visible for the same reason as MaxWatchedFilesPerDir: a test pinning the cap must read the real constant so a bump cannot silently disarm it. The registration count is a safe basis only because the considered-count is already bounded per directory by MaxWatchedFilesPerDir (see the .cpp comment).

◆ MaxWatchedFilesPerDir

constexpr int PhosphorTiles::ScriptedAlgorithmLoader::MaxWatchedFilesPerDir = 100
staticconstexpr

Per-directory cap on .luau files considered by one scan.

Public so a test can pin its spray fixture to the REAL value instead of a hardcoded copy. A copy is worse than it looks: raising the cap would leave the fixture below the new bound, so its loop would iterate over ids the cap never reached, assert nothing, and still pass its non-vacuity check.


The documentation for this class was generated from the following file: