Skip to content
TransBoxTransBox

QML UI Slots & HostContext

Map a slot name to a .qml file inside your package via ui_extensions in mod.json to replace the corresponding visual region without modifying the host application.

Default floating subtitle bar expanded (slot host reference)


1. Consumed Slots (safe to use)

SlotReplacesPurpose
overlay_backgroundSubtitle overlay backplateFrosted glass, gradients, noise
caption_viewSubtitle typesetting areaCustom bilingual layouts
audio_levelBottom-right volume / level meterWaveforms, spectrums
alert_capsuleMissing key / model-not-ready alert capsuleCustom alert UI
overlay_decorationsOverlay top-layer decorationsHUD cut corners, particles
style_bar_actionsControl-bar action extension areaExtra buttons
settings_backgroundSettings center backplateMatch the theme
history_backgroundHistory window backplate
dialog_backgroundDialog / modal backplate
window_backgroundMulti-window cascade fallback layerSettings/history fallback

Currently unconsumed (registered but no Loader — do not rely on them):
overlay_rootstyle_bar.

Non-standard key settings_view:
Does not go through the slot chain above; read by the settings-page plugin container for full engine/suite configuration UIs.


2. Cascade Fallback

Multi-window backgrounds try in this order:

  • Dialogs: dialog_backgroundwindow_backgroundoverlay_background
  • Settings/history: window_backgroundoverlay_background

Therefore, if you only write overlay_background, other windows may still reuse your backplate style.


3. window_backdrop

Declared in theme.json (not mod.json):

ValueMeaning
acrylicWindows acrylic
mica / mica_altMica (Win11)
blurBlur
noneNo system material

You can also call hostContext.window.setBackdrop("acrylic") from QML.


4. HostContext (overlay-class slots)

The host injects property var hostContext into the component root object:

qml
import QtQuick 2.15

Item {
    id: root
    property var hostContext: null

    readonly property color textColor:
        hostContext ? hostContext.style.textColor : "#ffffff"
    readonly property string translation:
        hostContext ? hostContext.subtitle.currTranslation : ""
    readonly property bool hovered:
        hostContext ? hostContext.window.hovered : false

    function callPython() {
        if (!hostContext) return
        hostContext.invoke("my.plugin.id", "ping", { "n": 1 })
    }

    Rectangle {
        anchors.fill: parent
        color: hostContext ? hostContext.style.bgColor : "#00000000"
        opacity: hostContext ? hostContext.style.bgOpacity : 1.0

        Text {
            anchors.centerIn: parent
            text: translation
            color: textColor
            font.pixelSize: hostContext ? hostContext.style.fontSize : 24
            font.family: hostContext ? hostContext.style.fontFamily : "sans-serif"
        }
    }
}

Subsystems

style
textColor · bgColor · fontOpacity · bgOpacity · fontSize · fontFamily · themeId · primary · primaryHover · primaryGlow · radiusLarge

subtitle
currSource · currTranslation · hasRealSubtitle · prevSource · prevTranslation · hasPrev · isTyping · isSourceActive · isTranslationActive

audio
isMicMuted · audioDuckingEnabled · playbackDevice

window
hovered · dragging · width · height · setBackdrop(type) · setClickThrough(bool)

RPC
hostContext.invoke(pluginId, action, params) → Python handle_actionaction_<action>(**params)


5. Extra Injected Properties (by slot)

SlotExtra properties / signals
overlay_background, etc.hovered, appState
caption_viewappState, bridge
alert_capsulealertType, alertCategory, showCapsule; signals closeRequested, gotoSettingsRequested, switchLocalRequested
style_bar_actionshostContext
Window backplateswindow, appState; may use customRadius

Multi-window backplates may declare:

qml
property bool enforceCustomRadius: true
property real customRadius: 16
property real customOpacity: 0.85

6. settings_view (plugin settings page)

mod.json:

json
{
  "ui_extensions": {
    "settings_view": "CustomSettingsView.qml"
  },
  "has_settings_tab": true,
  "tab_id": "my_plugin",
  "tab_title": "我的插件"
}

The component root object may declare (the host assigns them as needed):

qml
property string pluginId: ""
property var bridge: null
property var rootWin: null
property var pluginConfig: ({})

Save example:

qml
if (bridge) {
    bridge.setPluginConfigValue(pluginId, "gain_db", 12.5)
}

If you only need a form: you do not need settings_view — use config_schema instead.


7. Hands-on: Replace the Volume Bar

mod.json fragment:

json
{
  "type": "theme",
  "ui_extensions": { "audio_level": "CustomWaveform.qml" }
}
qml
import QtQuick 2.15

Item {
    id: root
    anchors.fill: parent
    property real level: 0.0
    property var hostContext: null

    // If the host does not provide a level signal, you can wire Connections to bridge yourself (version-dependent)
    Row {
        anchors.bottom: parent.bottom
        anchors.right: parent.right
        anchors.margins: 8
        spacing: 2
        opacity: root.level > 0.01 ? 0.95 : 0.0

        Repeater {
            model: 5
            Rectangle {
                width: 2
                height: Math.max(2, Math.min(10, root.level * 10))
                color: "#00f0ff"
            }
        }
    }
}

Complete runnable references: extensions/example_custom_waveform_ui/example_theme_cyberpunk/.


8. Design & Compatibility Tips

  1. Keep anchors.fill: parent on the component root so you do not break the host layout.
  2. Null-check every hostContext access so the component previews safely.
  3. Do not depend on global object names that do not appear in this document.
  4. Only one extension is enabled per slot at a time; enabling automatically applies mutual exclusion.

TransBox — empowering borderless cross-language communication for everyone