Merge branch 'bar-service'

This commit is contained in:
LemmyCook
2025-09-17 22:50:56 -04:00
11 changed files with 208 additions and 40 deletions
+7 -6
View File
@@ -8,6 +8,7 @@ import qs.Commons
import qs.Services
import qs.Widgets
import qs.Modules.Notification
import qs.Modules.Bar.Extras
Variants {
model: Quickshell.screens
@@ -88,7 +89,7 @@ Variants {
Repeater {
model: Settings.data.bar.widgets.left
delegate: NWidgetLoader {
delegate: BarWidgetLoader {
widgetId: (modelData.id !== undefined ? modelData.id : "")
widgetProps: {
"screen": root.modelData || null,
@@ -111,7 +112,7 @@ Variants {
Repeater {
model: Settings.data.bar.widgets.center
delegate: NWidgetLoader {
delegate: BarWidgetLoader {
widgetId: (modelData.id !== undefined ? modelData.id : "")
widgetProps: {
"screen": root.modelData || null,
@@ -135,7 +136,7 @@ Variants {
Repeater {
model: Settings.data.bar.widgets.right
delegate: NWidgetLoader {
delegate: BarWidgetLoader {
widgetId: (modelData.id !== undefined ? modelData.id : "")
widgetProps: {
"screen": root.modelData || null,
@@ -169,7 +170,7 @@ Variants {
Repeater {
model: Settings.data.bar.widgets.left
delegate: NWidgetLoader {
delegate: BarWidgetLoader {
widgetId: (modelData.id !== undefined ? modelData.id : "")
widgetProps: {
"screen": root.modelData || null,
@@ -194,7 +195,7 @@ Variants {
Repeater {
model: Settings.data.bar.widgets.center
delegate: NWidgetLoader {
delegate: BarWidgetLoader {
widgetId: (modelData.id !== undefined ? modelData.id : "")
widgetProps: {
"screen": root.modelData || null,
@@ -220,7 +221,7 @@ Variants {
Repeater {
model: Settings.data.bar.widgets.right
delegate: NWidgetLoader {
delegate: BarWidgetLoader {
widgetId: (modelData.id !== undefined ? modelData.id : "")
widgetProps: {
"screen": root.modelData || null,
@@ -8,12 +8,14 @@ Item {
property string widgetId: ""
property var widgetProps: ({})
property bool enabled: true
property string screenName: widgetProps.screen ? widgetProps.screen.name : ""
property string section: widgetProps.section || ""
property int sectionIndex: widgetProps.sectionWidgetIndex || 0
Connections {
target: ScalingService
function onScaleChanged(screenName, scale) {
if (loader.item && loader.item.screen && screenName === loader.item.screen.name) {
function onScaleChanged(aScreenName, scale) {
if (loader.item && loader.item.screen && aScreenName === screenName) {
loader.item['scaling'] = scale
}
}
@@ -27,7 +29,7 @@ Item {
id: loader
anchors.fill: parent
active: Settings.isLoaded && enabled && widgetId !== ""
active: Settings.isLoaded && widgetId !== ""
sourceComponent: {
if (!active) {
return null
@@ -45,18 +47,30 @@ Item {
}
}
// Register this widget instance with BarService
if (screenName && section) {
BarService.registerWidget(screenName, section, widgetId, sectionIndex, item)
}
if (item.hasOwnProperty("onLoaded")) {
item.onLoaded()
}
Logger.log("NWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
//Logger.log("BarWidgetLoader", "Loaded", widgetId, "on screen", item.screen.name)
}
Component.onDestruction: {
// Unregister when destroyed
if (screenName && section) {
BarService.unregisterWidget(screenName, section, widgetId, sectionIndex)
}
}
}
// Error handling
onWidgetIdChanged: {
if (widgetId && !BarWidgetRegistry.hasWidget(widgetId)) {
Logger.warn("WidgetLoader", "Widget not found in registry:", widgetId)
Logger.warn("BarWidgetLoader", "Widget not found in bar registry:", widgetId)
}
}
}
+1 -1
View File
@@ -86,7 +86,7 @@ Item {
id: pill
compact: (Settings.data.bar.density === "compact")
rightOpen: BarWidgetRegistry.getPillDirection(root)
rightOpen: BarService.getPillDirection(root)
icon: testMode ? BatteryService.getIcon(testPercent, testCharging, true) : BatteryService.getIcon(percent, charging, isReady)
text: (isReady || testMode) ? Math.round(percent) : "-"
suffix: "%"
+1 -1
View File
@@ -78,7 +78,7 @@ Item {
id: pill
compact: (Settings.data.bar.density === "compact")
rightOpen: BarWidgetRegistry.getPillDirection(root)
rightOpen: BarService.getPillDirection(root)
icon: getIcon()
autoHide: false // Important to be false so we can hover as long as we want
text: {
+1 -1
View File
@@ -47,7 +47,7 @@ Item {
BarPill {
id: pill
rightOpen: BarWidgetRegistry.getPillDirection(root)
rightOpen: BarService.getPillDirection(root)
icon: customIcon
text: _dynamicText
compact: (Settings.data.bar.density === "compact")
+1 -1
View File
@@ -44,7 +44,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
compact: (Settings.data.bar.density === "compact")
rightOpen: BarWidgetRegistry.getPillDirection(root)
rightOpen: BarService.getPillDirection(root)
icon: "keyboard"
autoHide: false // Important to be false so we can hover as long as we want
text: currentLayout.toUpperCase()
+1 -1
View File
@@ -89,7 +89,7 @@ Item {
BarPill {
id: pill
rightOpen: BarWidgetRegistry.getPillDirection(root)
rightOpen: BarService.getPillDirection(root)
icon: getIcon()
compact: (Settings.data.bar.density === "compact")
autoHide: false // Important to be false so we can hover as long as we want
+1 -1
View File
@@ -76,7 +76,7 @@ Item {
id: pill
compact: (Settings.data.bar.density === "compact")
rightOpen: BarWidgetRegistry.getPillDirection(root)
rightOpen: BarService.getPillDirection(root)
icon: getIcon()
autoHide: false // Important to be false so we can hover as long as we want
text: Math.floor(AudioService.volume * 100)
+4 -2
View File
@@ -27,7 +27,8 @@ Item {
IpcHandler {
target: "notifications"
function toggleHistory() {
notificationHistoryPanel.toggle()
// Will attempt to open the panel next to the bar button if any.
notificationHistoryPanel.toggle(BarService.lookupWidget("NotificationHistory"))
}
function toggleDND() {
Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb
@@ -118,7 +119,8 @@ Item {
IpcHandler {
target: "sidePanel"
function toggle() {
sidePanel.toggle()
// Will attempt to open the panel next to the bar button if any.
sidePanel.toggle(BarService.lookupWidget("SidePanelToggle"))
}
}
+171
View File
@@ -0,0 +1,171 @@
pragma Singleton
import Quickshell
import qs.Commons
Singleton {
id: root
// Registry to store actual widget instances
// Key format: "screenName|section|widgetId|index"
property var widgetInstances: ({})
// Register a widget instance
function registerWidget(screenName, section, widgetId, index, instance) {
const key = [screenName, section, widgetId, index].join("|")
widgetInstances[key] = {
"key": key,
"screenName": screenName,
"section": section,
"widgetId": widgetId,
"index": index,
"instance": instance
}
Logger.log("BarService", "Registered widget:", key)
}
// Unregister a widget instance
function unregisterWidget(screenName, section, widgetId, index) {
const key = [screenName, section, widgetId, index].join("|")
delete widgetInstances[key]
Logger.log("BarService", "Unregistered widget:", key)
}
// Lookup a specific widget instance (returns the actual QML instance)
function lookupWidget(widgetId, screenName = null, section = null) {
// If looking for a specific instance
if (screenName && section !== null) {
for (var key in widgetInstances) {
var widget = widgetInstances[key]
if (widget.widgetId === widgetId && widget.screenName === screenName && widget.section === section) {
return widget.instance
}
}
}
// Return first match if no specific screen/section specified
for (var key in widgetInstances) {
var widget = widgetInstances[key]
if (widget.widgetId === widgetId) {
if (!screenName || widget.screenName === screenName) {
if (section === null || widget.section === section) {
return widget.instance
}
}
}
}
return undefined
}
// Get all instances of a widget type
function getAllWidgetInstances(widgetId = null, screenName = null, section = null) {
var instances = []
for (var key in widgetInstances) {
var widget = widgetInstances[key]
var matches = true
if (widgetId && widget.widgetId !== widgetId)
matches = false
if (screenName && widget.screenName !== screenName)
matches = false
if (section !== null && widget.section !== section)
matches = false
if (matches) {
instances.push(widget.instance)
}
}
return instances
}
// Get widget with full metadata
function getWidgetWithMetadata(widgetId, screenName = null, section = null) {
for (var key in widgetInstances) {
var widget = widgetInstances[key]
if (widget.widgetId === widgetId) {
if (!screenName || widget.screenName === screenName) {
if (section === null || widget.section === section) {
return widget
}
}
}
}
return undefined
}
// Get all widgets in a specific section
function getWidgetsBySection(section, screenName = null) {
var widgets = []
for (var key in widgetInstances) {
var widget = widgetInstances[key]
if (widget.section === section) {
if (!screenName || widget.screenName === screenName) {
widgets.push(widget.instance)
}
}
}
// Sort by index to maintain order
widgets.sort(function (a, b) {
var aWidget = getWidgetWithMetadata(a.widgetId, a.screen?.name, a.section)
var bWidget = getWidgetWithMetadata(b.widgetId, b.screen?.name, b.section)
return (aWidget?.index || 0) - (bWidget?.index || 0)
})
return widgets
}
// Get all registered widgets (for debugging)
function getAllRegisteredWidgets() {
var result = []
for (var key in widgetInstances) {
result.push({
"key": key,
"widgetId": widgetInstances[key].widgetId,
"section": widgetInstances[key].section,
"screenName": widgetInstances[key].screenName,
"index": widgetInstances[key].index
})
}
return result
}
// Check if a widget type exists in a section
function hasWidget(widgetId, section = null, screenName = null) {
for (var key in widgetInstances) {
var widget = widgetInstances[key]
if (widget.widgetId === widgetId) {
if (section === null || widget.section === section) {
if (!screenName || widget.screenName === screenName) {
return true
}
}
}
}
return false
}
// Get pill direction for a widget instance
function getPillDirection(widgetInstance) {
try {
if (widgetInstance.section === "left") {
return true
} else if (widgetInstance.section === "right") {
return false
} else {
// middle section
if (widgetInstance.sectionWidgetIndex < widgetInstance.sectionWidgetsCount / 2) {
return false
} else {
return true
}
}
} catch (e) {
Logger.error(e)
}
return false
}
}
-20
View File
@@ -204,24 +204,4 @@ Singleton {
function widgetHasUserSettings(id) {
return (widgetMetadata[id] !== undefined) && (widgetMetadata[id].allowUserSettings === true)
}
function getPillDirection(widget) {
try {
if (widget.section === "left") {
return true
} else if (widget.section === "right") {
return false
} else {
// middle section
if (widget.sectionWidgetIndex < widget.sectionWidgetsCount / 2) {
return false
} else {
return true
}
}
} catch (e) {
Logger.error(e)
}
return false
}
}