Add visual bar customizer
Each layout entry is now an object — {id, ...inline settings} — instead
of a (name, separate modules map) pair. Multiple instances of the same
widget are trivially supported (spacer is the main beneficiary). Settings
travel with the entry, so reordering keeps them attached.
shell.qml:
- normalizeLayout converts string entries to {id} and drops invalid ones
- ModuleSlot binds to a full entry; moduleName and moduleSettings derive
from it via entryId/entrySettings helpers
- centerAnchor lookup walks layoutEntries directly
- builtinBarConfig defaults use the object form
- README + bar-defaults.json updated to the new schema
bar-settings/ (new Quickshell config):
- Top toolbar with Reset / Save and Position / centerAnchor dropdowns
- Three section editors (left/center/right) with current widgets shown
as cards: name + description + move up/down/settings/remove buttons
- '+ Add widget' menu per section, sorted alphabetically by display name
(only spacer can repeat; everything else is one per bar)
- Per-widget settings dialog (FloatingWindow) loads an inline schema for
widgets in the catalog. Initial schemas: spacer (size), calendar
(formats), brightness (step)
- FileView { atomicWrites } writes to ~/.config/omarchy/bar.json on Save
omarchy-launch-bar-settings + hypr window rules pin the settings window
to a 760px floating square. controlCenter gains a 'Customize bar…' button
that launches it.
This commit is contained in:
@@ -9,21 +9,40 @@ This is the Quickshell implementation of the Omarchy status bar.
|
||||
- User overrides live in `~/.config/omarchy/bar.json` and are merged over defaults at runtime.
|
||||
- `omarchy-style-bar-position` updates only the user override file.
|
||||
|
||||
Example user override:
|
||||
## Customizing
|
||||
|
||||
The bar reads `~/.local/share/omarchy/default/quickshell/bar/bar-defaults.json`, then deep-merges `~/.config/omarchy/bar.json` on top of it. Each `layout.{left,center,right}` entry is an object: at minimum `{ "id": "<widget>" }`, plus any inline settings the widget reads.
|
||||
|
||||
Launch the visual editor with `omarchy launch bar-settings` (or run `omarchy-launch-bar-settings`) to reorder widgets, add/remove them, and tweak per-widget options without editing JSON by hand.
|
||||
|
||||
Example `bar.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"position": "top",
|
||||
"centerAnchor": "calendar",
|
||||
"layout": {
|
||||
"left": ["omarchy", "workspacesPro"],
|
||||
"center": ["media", "calendar", "weatherFlyout"],
|
||||
"right": ["systemStats", "notificationCenter", "bluetoothPanel", "networkPanel", "audioPanel", "brightness", "powerProfile", "battery", "powerMenu"]
|
||||
},
|
||||
"centerAnchor": "calendar"
|
||||
"left": [
|
||||
{ "id": "omarchy" },
|
||||
{ "id": "spacer", "size": 12 },
|
||||
{ "id": "workspacesPro" }
|
||||
],
|
||||
"center": [
|
||||
{ "id": "media" },
|
||||
{ "id": "calendar", "format": "HH:mm" }
|
||||
],
|
||||
"right": [
|
||||
{ "id": "systemStats" },
|
||||
{ "id": "audioPanel" },
|
||||
{ "id": "battery" },
|
||||
{ "id": "controlCenter" },
|
||||
{ "id": "powerMenu" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`centerAnchor` pins one center module to the exact horizontal/vertical center and flanks others around it.
|
||||
`centerAnchor` pins one center module to the exact horizontal/vertical center and flanks others around it. Set to an empty string to disable anchoring (the center list is centered as a group).
|
||||
|
||||
## Module catalogue
|
||||
|
||||
@@ -58,23 +77,18 @@ All widgets work in `top`, `bottom`, `left`, and `right` positions. Popups ancho
|
||||
|
||||
## Custom user modules
|
||||
|
||||
Add a module name to a layout list, then define it under `modules` in `~/.config/omarchy/bar.json`.
|
||||
The schema accepts arbitrary module ids that you provide. Set `type` to `command` for shell-driven output or `qml` for a custom QML widget.
|
||||
|
||||
For simple text/JSON output, use a command module:
|
||||
Command module:
|
||||
|
||||
```json
|
||||
{
|
||||
"layout": {
|
||||
"right": ["tray", "vpn", "audioPanel", "cpu"]
|
||||
},
|
||||
"modules": {
|
||||
"vpn": {
|
||||
"type": "command",
|
||||
"exec": "~/.config/omarchy/bar/scripts/vpn-status",
|
||||
"interval": 5,
|
||||
"tooltip": "VPN",
|
||||
"onClick": "nm-connection-editor"
|
||||
}
|
||||
"right": [
|
||||
{ "id": "tray" },
|
||||
{ "id": "vpn", "type": "command", "exec": "~/.config/omarchy/bar/scripts/vpn-status", "interval": 5, "tooltip": "VPN", "onClick": "nm-connection-editor" },
|
||||
{ "id": "audioPanel" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -85,17 +99,15 @@ The command may print plain text or Waybar-style JSON, for example:
|
||||
{"text":"","tooltip":"Work VPN","class":"active"}
|
||||
```
|
||||
|
||||
For advanced custom UI, use QML:
|
||||
QML module:
|
||||
|
||||
```json
|
||||
{
|
||||
"layout": {
|
||||
"right": ["gpu", "audioPanel", "cpu"]
|
||||
},
|
||||
"modules": {
|
||||
"gpu": {
|
||||
"type": "qml"
|
||||
}
|
||||
"right": [
|
||||
{ "id": "gpu", "type": "qml" },
|
||||
{ "id": "audioPanel" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -3,20 +3,34 @@
|
||||
"fontFamily": "JetBrainsMono Nerd Font",
|
||||
"centerAnchor": "calendar",
|
||||
"layout": {
|
||||
"left": ["omarchy", "workspacesPro", "activeWindow"],
|
||||
"center": ["media", "calendar", "weatherFlyout", "update", "voxtype", "screenRecording", "idle", "notifications"],
|
||||
"right": ["tray", "systemStats", "microphone", "bluetoothPanel", "networkPanel", "audioPanel", "nightLight", "brightness", "powerProfile", "battery", "controlCenter", "powerMenu"]
|
||||
},
|
||||
"modules": {
|
||||
"calendar": {
|
||||
"format": "dddd HH:mm",
|
||||
"formatAlt": "dd MMMM 'W'ww yyyy",
|
||||
"verticalFormat": "HH\n—\nmm"
|
||||
},
|
||||
"clock": {
|
||||
"format": "dddd HH:mm",
|
||||
"formatAlt": "dd MMMM 'W'ww yyyy",
|
||||
"verticalFormat": "HH\n—\nmm"
|
||||
}
|
||||
"left": [
|
||||
{ "id": "omarchy" },
|
||||
{ "id": "workspacesPro" },
|
||||
{ "id": "activeWindow" }
|
||||
],
|
||||
"center": [
|
||||
{ "id": "media" },
|
||||
{ "id": "calendar", "format": "dddd HH:mm", "formatAlt": "dd MMMM 'W'ww yyyy", "verticalFormat": "HH\n—\nmm" },
|
||||
{ "id": "weatherFlyout" },
|
||||
{ "id": "update" },
|
||||
{ "id": "voxtype" },
|
||||
{ "id": "screenRecording" },
|
||||
{ "id": "idle" },
|
||||
{ "id": "notifications" }
|
||||
],
|
||||
"right": [
|
||||
{ "id": "tray" },
|
||||
{ "id": "systemStats" },
|
||||
{ "id": "microphone" },
|
||||
{ "id": "bluetoothPanel" },
|
||||
{ "id": "networkPanel" },
|
||||
{ "id": "audioPanel" },
|
||||
{ "id": "nightLight" },
|
||||
{ "id": "brightness" },
|
||||
{ "id": "powerProfile" },
|
||||
{ "id": "battery" },
|
||||
{ "id": "controlCenter" },
|
||||
{ "id": "powerMenu" }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,22 +21,21 @@ ShellRoot {
|
||||
fontFamily: "JetBrainsMono Nerd Font",
|
||||
centerAnchor: "clock",
|
||||
layout: {
|
||||
left: ["omarchy", "workspaces"],
|
||||
center: ["clock", "weather", "update", "voxtype", "screenRecording", "idle", "notifications"],
|
||||
right: ["tray", "bluetooth", "network", "audio", "cpu", "battery"]
|
||||
},
|
||||
modules: {
|
||||
clock: {
|
||||
format: "dddd HH:mm",
|
||||
formatAlt: "dd MMMM 'W'ww yyyy",
|
||||
verticalFormat: "HH\n—\nmm"
|
||||
}
|
||||
left: [{ id: "omarchy" }, { id: "workspaces" }],
|
||||
center: [
|
||||
{ id: "clock", format: "dddd HH:mm", formatAlt: "dd MMMM 'W'ww yyyy", verticalFormat: "HH\n—\nmm" },
|
||||
{ id: "weather" }, { id: "update" }, { id: "voxtype" },
|
||||
{ id: "screenRecording" }, { id: "idle" }, { id: "notifications" }
|
||||
],
|
||||
right: [
|
||||
{ id: "tray" }, { id: "bluetooth" }, { id: "network" },
|
||||
{ id: "audio" }, { id: "cpu" }, { id: "battery" }
|
||||
]
|
||||
}
|
||||
})
|
||||
property var defaultBarConfig: builtinBarConfig
|
||||
property var userBarConfig: ({})
|
||||
property var layoutConfig: builtinBarConfig.layout
|
||||
property var moduleConfig: builtinBarConfig.modules
|
||||
property string centerAnchor: "clock"
|
||||
property int barConfigSerial: 0
|
||||
property string position: "top"
|
||||
@@ -145,14 +144,38 @@ ShellRoot {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeLayoutEntry(entry) {
|
||||
if (typeof entry === "string") return { id: entry }
|
||||
if (isPlainObject(entry) && entry.id) return entry
|
||||
return null
|
||||
}
|
||||
|
||||
function normalizeLayoutSection(list) {
|
||||
if (!Array.isArray(list)) return []
|
||||
var result = []
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var normalized = normalizeLayoutEntry(list[i])
|
||||
if (normalized) result.push(normalized)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function normalizeLayout(layout) {
|
||||
if (!isPlainObject(layout)) layout = builtinBarConfig.layout
|
||||
return {
|
||||
left: normalizeLayoutSection(layout.left),
|
||||
center: normalizeLayoutSection(layout.center),
|
||||
right: normalizeLayoutSection(layout.right)
|
||||
}
|
||||
}
|
||||
|
||||
function applyBarConfig() {
|
||||
var config = mergeConfig(defaultBarConfig, userBarConfig)
|
||||
|
||||
position = normalizePosition(config.position)
|
||||
fontFamily = String(config.fontFamily || "JetBrainsMono Nerd Font")
|
||||
centerAnchor = String(config.centerAnchor || "clock")
|
||||
layoutConfig = isPlainObject(config.layout) ? config.layout : builtinBarConfig.layout
|
||||
moduleConfig = isPlainObject(config.modules) ? config.modules : {}
|
||||
layoutConfig = normalizeLayout(config.layout)
|
||||
barConfigSerial++
|
||||
}
|
||||
|
||||
@@ -166,42 +189,53 @@ ShellRoot {
|
||||
applyBarConfig()
|
||||
}
|
||||
|
||||
function layoutModules(region) {
|
||||
function layoutEntries(region) {
|
||||
var serial = barConfigSerial
|
||||
var modules = layoutConfig ? layoutConfig[region] : null
|
||||
return Array.isArray(modules) ? modules : []
|
||||
var entries = layoutConfig ? layoutConfig[region] : null
|
||||
return Array.isArray(entries) ? entries : []
|
||||
}
|
||||
|
||||
function moduleSettings(name) {
|
||||
var serial = barConfigSerial
|
||||
var settings = moduleConfig ? moduleConfig[String(name)] : null
|
||||
return isPlainObject(settings) ? settings : {}
|
||||
function entrySettings(entry) {
|
||||
if (!isPlainObject(entry)) return {}
|
||||
var copy = {}
|
||||
for (var key in entry) {
|
||||
if (key === "id") continue
|
||||
copy[key] = entry[key]
|
||||
}
|
||||
return copy
|
||||
}
|
||||
|
||||
function moduleString(name, key, fallback) {
|
||||
var value = moduleSettings(name)[key]
|
||||
function entryId(entry) {
|
||||
if (typeof entry === "string") return entry
|
||||
if (isPlainObject(entry) && entry.id) return String(entry.id)
|
||||
return ""
|
||||
}
|
||||
|
||||
function moduleString(entry, key, fallback) {
|
||||
var settings = entrySettings(entry)
|
||||
var value = settings[key]
|
||||
return value === undefined || value === null ? fallback : String(value)
|
||||
}
|
||||
|
||||
function moduleIndex(modules, name) {
|
||||
if (!Array.isArray(modules)) return -1
|
||||
function entryIndex(entries, name) {
|
||||
if (!Array.isArray(entries)) return -1
|
||||
|
||||
for (var i = 0; i < modules.length; i++) {
|
||||
if (String(modules[i]) === name)
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
if (entryId(entries[i]) === name)
|
||||
return i
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
function modulesBefore(modules, name) {
|
||||
var index = moduleIndex(modules, name)
|
||||
return index <= 0 ? [] : modules.slice(0, index)
|
||||
function entriesBefore(entries, name) {
|
||||
var index = entryIndex(entries, name)
|
||||
return index <= 0 ? [] : entries.slice(0, index)
|
||||
}
|
||||
|
||||
function modulesAfter(modules, name) {
|
||||
var index = moduleIndex(modules, name)
|
||||
return index === -1 ? [] : modules.slice(index + 1)
|
||||
function entriesAfter(entries, name) {
|
||||
var index = entryIndex(entries, name)
|
||||
return index === -1 ? [] : entries.slice(index + 1)
|
||||
}
|
||||
|
||||
function builtinModuleComponent(name) {
|
||||
@@ -241,8 +275,8 @@ ShellRoot {
|
||||
return value !== "" && value.indexOf("..") === -1 && value[0] !== "/"
|
||||
}
|
||||
|
||||
function customModuleType(name) {
|
||||
var settings = moduleSettings(name)
|
||||
function customModuleType(entry) {
|
||||
var settings = entrySettings(entry)
|
||||
var type = String(settings.type || "")
|
||||
if (type) return type
|
||||
if (settings.exec) return "command"
|
||||
@@ -250,8 +284,9 @@ ShellRoot {
|
||||
return ""
|
||||
}
|
||||
|
||||
function customModuleSource(name) {
|
||||
var settings = moduleSettings(name)
|
||||
function customModuleSource(entry) {
|
||||
var settings = entrySettings(entry)
|
||||
var name = entryId(entry)
|
||||
var source = settings.source ? expandPath(settings.source) : ""
|
||||
if (!source && customModuleSafeName(name))
|
||||
source = omarchyConfigDir + "/bar/modules/" + String(name) + ".qml"
|
||||
@@ -601,14 +636,26 @@ ShellRoot {
|
||||
root.run("hyprctl dispatch " + shellQuote("hl.dsp.focus({ workspace = \"" + id + "\" })"))
|
||||
}
|
||||
|
||||
function clockEntry() {
|
||||
var serial = barConfigSerial
|
||||
var sections = ["left", "center", "right"]
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
var entries = layoutEntries(sections[i])
|
||||
var idx = entryIndex(entries, "clock")
|
||||
if (idx !== -1) return entries[idx]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function clockText() {
|
||||
var entry = clockEntry()
|
||||
if (clockAlt)
|
||||
return Qt.formatDateTime(systemClock.date, moduleString("clock", "formatAlt", "dd MMMM 'W'ww yyyy"))
|
||||
return Qt.formatDateTime(systemClock.date, moduleString(entry, "formatAlt", "dd MMMM 'W'ww yyyy"))
|
||||
|
||||
if (vertical)
|
||||
return Qt.formatDateTime(systemClock.date, moduleString("clock", "verticalFormat", "HH\n—\nmm"))
|
||||
return Qt.formatDateTime(systemClock.date, moduleString(entry, "verticalFormat", "HH\n—\nmm"))
|
||||
|
||||
return Qt.formatDateTime(systemClock.date, moduleString("clock", "format", "dddd HH:mm"))
|
||||
return Qt.formatDateTime(systemClock.date, moduleString(entry, "format", "dddd HH:mm"))
|
||||
}
|
||||
|
||||
SystemClock {
|
||||
@@ -947,19 +994,26 @@ ShellRoot {
|
||||
Component { id: cpuModuleComponent; CpuModule {} }
|
||||
Component { id: batteryModuleComponent; BatteryModule {} }
|
||||
|
||||
function findCenterAnchorEntry() {
|
||||
var entries = root.layoutEntries("center")
|
||||
var idx = root.entryIndex(entries, root.centerAnchor)
|
||||
return idx === -1 ? null : entries[idx]
|
||||
}
|
||||
|
||||
component LeftModules: ModuleList {
|
||||
modules: root.layoutModules("left")
|
||||
entries: root.layoutEntries("left")
|
||||
}
|
||||
|
||||
component RightModules: ModuleList {
|
||||
modules: root.layoutModules("right")
|
||||
entries: root.layoutEntries("right")
|
||||
}
|
||||
|
||||
component CenterModules: Item {
|
||||
id: centerRoot
|
||||
|
||||
property var modules: root.layoutModules("center")
|
||||
readonly property bool hasAnchor: root.moduleIndex(modules, root.centerAnchor) !== -1
|
||||
property var entries: root.layoutEntries("center")
|
||||
readonly property bool hasAnchor: root.entryIndex(entries, root.centerAnchor) !== -1
|
||||
readonly property var anchorEntry: root.findCenterAnchorEntry()
|
||||
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
@@ -974,13 +1028,13 @@ ShellRoot {
|
||||
|
||||
ModuleList {
|
||||
visible: !centerRoot.hasAnchor
|
||||
modules: centerRoot.modules
|
||||
entries: centerRoot.entries
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
ModuleList {
|
||||
visible: centerRoot.hasAnchor
|
||||
modules: root.modulesBefore(centerRoot.modules, root.centerAnchor)
|
||||
entries: root.entriesBefore(centerRoot.entries, root.centerAnchor)
|
||||
anchors.right: centerAnchorModule.left
|
||||
anchors.verticalCenter: centerAnchorModule.verticalCenter
|
||||
}
|
||||
@@ -988,13 +1042,13 @@ ShellRoot {
|
||||
ModuleSlot {
|
||||
id: centerAnchorModule
|
||||
visible: centerRoot.hasAnchor
|
||||
moduleName: root.centerAnchor
|
||||
entry: centerRoot.anchorEntry
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
ModuleList {
|
||||
visible: centerRoot.hasAnchor
|
||||
modules: root.modulesAfter(centerRoot.modules, root.centerAnchor)
|
||||
entries: root.entriesAfter(centerRoot.entries, root.centerAnchor)
|
||||
anchors.left: centerAnchorModule.right
|
||||
anchors.verticalCenter: centerAnchorModule.verticalCenter
|
||||
}
|
||||
@@ -1009,13 +1063,13 @@ ShellRoot {
|
||||
|
||||
ModuleList {
|
||||
visible: !centerRoot.hasAnchor
|
||||
modules: centerRoot.modules
|
||||
entries: centerRoot.entries
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
ModuleList {
|
||||
visible: centerRoot.hasAnchor
|
||||
modules: root.modulesBefore(centerRoot.modules, root.centerAnchor)
|
||||
entries: root.entriesBefore(centerRoot.entries, root.centerAnchor)
|
||||
anchors.bottom: centerAnchorModule.top
|
||||
anchors.horizontalCenter: centerAnchorModule.horizontalCenter
|
||||
}
|
||||
@@ -1023,13 +1077,13 @@ ShellRoot {
|
||||
ModuleSlot {
|
||||
id: centerAnchorModule
|
||||
visible: centerRoot.hasAnchor
|
||||
moduleName: root.centerAnchor
|
||||
entry: centerRoot.anchorEntry
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
ModuleList {
|
||||
visible: centerRoot.hasAnchor
|
||||
modules: root.modulesAfter(centerRoot.modules, root.centerAnchor)
|
||||
entries: root.entriesAfter(centerRoot.entries, root.centerAnchor)
|
||||
anchors.top: centerAnchorModule.bottom
|
||||
anchors.horizontalCenter: centerAnchorModule.horizontalCenter
|
||||
}
|
||||
@@ -1040,9 +1094,9 @@ ShellRoot {
|
||||
component ModuleList: Loader {
|
||||
id: moduleListRoot
|
||||
|
||||
property var modules: []
|
||||
property var entries: []
|
||||
|
||||
visible: modules.length > 0
|
||||
visible: entries.length > 0
|
||||
sourceComponent: root.vertical ? verticalModuleList : horizontalModuleList
|
||||
width: item ? item.implicitWidth : 0
|
||||
height: item ? item.implicitHeight : 0
|
||||
@@ -1054,11 +1108,11 @@ ShellRoot {
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: moduleListRoot.modules
|
||||
model: moduleListRoot.entries
|
||||
|
||||
ModuleSlot {
|
||||
required property var modelData
|
||||
moduleName: String(modelData)
|
||||
entry: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1071,11 +1125,11 @@ ShellRoot {
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: moduleListRoot.modules
|
||||
model: moduleListRoot.entries
|
||||
|
||||
ModuleSlot {
|
||||
required property var modelData
|
||||
moduleName: String(modelData)
|
||||
entry: modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1085,8 +1139,10 @@ ShellRoot {
|
||||
component ModuleSlot: Item {
|
||||
id: slot
|
||||
|
||||
required property string moduleName
|
||||
readonly property string customType: root.customModuleType(moduleName)
|
||||
required property var entry
|
||||
readonly property string moduleName: root.entryId(entry)
|
||||
readonly property var moduleSettings: root.entrySettings(entry)
|
||||
readonly property string customType: root.customModuleType(entry)
|
||||
readonly property var builtinComponent: customType ? null : root.builtinModuleComponent(moduleName)
|
||||
readonly property string firstPartySource: customType || builtinComponent ? "" : root.firstPartyWidgetSource(moduleName)
|
||||
readonly property bool qmlCustom: customType === "qml"
|
||||
@@ -1109,35 +1165,33 @@ ShellRoot {
|
||||
Loader {
|
||||
id: qmlLoader
|
||||
active: slot.qmlCustom || slot.firstParty
|
||||
source: slot.qmlCustom ? root.customModuleSource(slot.moduleName) : (slot.firstParty ? slot.firstPartySource : "")
|
||||
source: slot.qmlCustom ? root.customModuleSource(slot.entry) : (slot.firstParty ? slot.firstPartySource : "")
|
||||
anchors.fill: parent
|
||||
onLoaded: slot.injectProps()
|
||||
}
|
||||
|
||||
onModuleSettingsChanged: injectProps()
|
||||
|
||||
function injectProps() {
|
||||
var target = qmlLoader.item
|
||||
if (!target) return
|
||||
if ("bar" in target) target.bar = root
|
||||
if ("moduleName" in target) target.moduleName = moduleName
|
||||
if ("settings" in target) target.settings = root.moduleSettings(moduleName)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onBarConfigSerialChanged() { slot.injectProps() }
|
||||
if ("settings" in target) target.settings = moduleSettings
|
||||
}
|
||||
|
||||
Component {
|
||||
id: customCommandModuleComponent
|
||||
CustomCommandModule { moduleName: slot.moduleName }
|
||||
CustomCommandModule { entry: slot.entry }
|
||||
}
|
||||
}
|
||||
|
||||
component CustomCommandModule: ModuleButton {
|
||||
id: customRoot
|
||||
|
||||
required property string moduleName
|
||||
property var settings: root.moduleSettings(moduleName)
|
||||
required property var entry
|
||||
readonly property string moduleName: root.entryId(entry)
|
||||
readonly property var settings: root.entrySettings(entry)
|
||||
property string outputText: ""
|
||||
property string outputTooltip: ""
|
||||
property bool outputActive: false
|
||||
|
||||
@@ -322,6 +322,16 @@ Item {
|
||||
color: Qt.rgba(root.bar.foreground.r, root.bar.foreground.g, root.bar.foreground.b, 0.12)
|
||||
}
|
||||
|
||||
Common.PillButton {
|
||||
width: parent.width
|
||||
iconText: ""
|
||||
text: "Customize bar…"
|
||||
foreground: root.bar.foreground
|
||||
horizontalPadding: 10
|
||||
verticalPadding: 8
|
||||
onClicked: { root.run("omarchy-launch-bar-settings"); root.popupOpen = false }
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 6
|
||||
|
||||
Reference in New Issue
Block a user