XDG Icon Theme Specification 0.13 lookup + the Qt image provider that lets QML consume the resulting QImage payloads through a QUrl source.
IconThemeResolver**: spec-compliant theme walk. Detects the active theme via QIcon::themeName() (which the Qt platform plugin sources from Plasma, GTK, or xsettings as available), parses each theme's index.theme, follows Inherits= chains, and falls back to Hicolor or direct filesystem search for absolute paths. iconForName(name, size, scale, extraThemeDir) returns the best-match QImage by the spec's distance algorithm.IconImageProvider**: Qt image provider mounted at image://phosphor-service-icontheme/. The publisher (e.g. a tray-item model holding QImage payloads from D-Bus) calls IconImageProvider::setImage(id, image). The consumer binds Image.source to a URL of the form image://phosphor-service-icontheme/<id>?v=<cacheKey>, and Qt routes that back through requestImage() which reads the QImage out of the thread-safe static registry. The ?v= suffix exists only to force QML's Image element to re-fetch when the underlying QImage data changes (QML's Image only reloads when the URL string differs).| Type | Role |
|---|---|
IconThemeResolver | Singleton XDG icon resolver. iconForName + decodePixmaps static for raw IconPixmap byte blobs. |
IconImageProvider | QQuickImageProvider with a process-global registry; setImage / clearImage from publishers. |
C++ shell composition root:
#include <PhosphorServiceIconTheme/QmlRegistration.h>
int main(int argc, char** argv)
{
QGuiApplication app(argc, argv);
PhosphorServiceIconTheme::registerQmlTypes(); // exposes IconThemeResolver singleton
QQmlApplicationEngine engine;
PhosphorServiceIconTheme::installImageProvider(&engine); // mounts image://phosphor-service-icontheme/
// ... load shell.qml
}QML consumer (resolve an XDG icon, then route the resulting QImage through the image provider so QML's Image.source can consume it as a URL):
import Phosphor.Service.IconTheme 1.0
import QtQuick
Image {
// IconThemeResolver.iconForName returns a QImage, which Image.source
// (a QUrl) cannot bind to directly. The C++ side must call
// IconImageProvider::setImage(id, image) and then expose the URL
// form below; the snippet here illustrates the QML end of that
// contract.
property string trayKey: "tray-audio-volume-high"
source: "image://phosphor-service-icontheme/" + trayKey + "?v=" + cacheVersion
property int cacheVersion: 0
sourceSize: Qt.size(24, 24)
}Publisher (typically internal to a service that holds raw QImage payloads, e.g. phosphor-service-sni's tray-item model):
#include <PhosphorServiceIconTheme/IconImageProvider.h>
#include <PhosphorServiceIconTheme/QmlRegistration.h>
const QString trayKey = QStringLiteral("tray-audio-volume-high");
PhosphorServiceIconTheme::IconImageProvider::setImage(trayKey, qimage);
// then expose the QML-bindable URL:
const QString url = QStringLiteral("image://")
+ QString::fromLatin1(PhosphorServiceIconTheme::imageProviderUrlHost())
+ QLatin1Char('/') + trayKey + QStringLiteral("?v=")
+ QString::number(qimage.cacheKey());QQmlEngines across reload cycles. The icon payload is valid across all of them. Coarse single-mutex locking is fine at human update rates.imageProviderUrlHost() accessor exists so publishers don't hard-code the host string. A rename here breaks the link rather than failing silently at runtime.?v= cache busting.** Image re-fetches only on URL change. The publisher appends ?v=cacheKey() so a fresh setImage for the same id forces a rebind. requestImage strips the query before lookup.Shipped. Extracted from the original phosphor-services umbrella as one of four per-domain siblings. The umbrella is gone, with no backwards-compat shim (per feedback_no_legacy_shims). The URL host was renamed from phosphor-services to phosphor-service-icontheme for consistency with the new library name, and consumers of the old URL fail loudly rather than silently fall back. Namespace PhosphorServices::IconThemeResolver becomes PhosphorServiceIconTheme::IconThemeResolver, QML module Phosphor.Services becomes Phosphor.Service.IconTheme.
phosphor-service-sni calls IconThemeResolver::instance()->iconForName(...) for XDG-themed tray icons and routes raw IconPixmap blobs through IconImageProvider::setImage for QML binding.The QML singleton (IconThemeResolver under Phosphor.Service.IconTheme 1.0) is registered for future bar widgets and third-party shells. The bundled examples/phosphor-shell/ does not import it yet.