fedora
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Services.UPower
|
||||
import qs.Commons
|
||||
import qs.Modules.Bar.Extras
|
||||
import qs.Services.Hardware
|
||||
import qs.Services.Networking
|
||||
import qs.Services.UI
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property ShellScreen screen
|
||||
|
||||
// Widget properties passed from Bar.qml for per-instance settings
|
||||
property string widgetId: ""
|
||||
property string section: ""
|
||||
property int sectionWidgetIndex: -1
|
||||
property int sectionWidgetsCount: 0
|
||||
|
||||
property var widgetMetadata: BarWidgetRegistry.widgetMetadata[widgetId] ?? {}
|
||||
// Explicit screenName property ensures reactive binding when screen changes
|
||||
readonly property string screenName: screen ? screen.name : ""
|
||||
property var widgetSettings: {
|
||||
if (section && sectionWidgetIndex >= 0 && screenName) {
|
||||
var widgets = Settings.getBarWidgetsForScreen(screenName)[section];
|
||||
if (widgets && sectionWidgetIndex < widgets.length) {
|
||||
return widgets[sectionWidgetIndex];
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
readonly property string barPosition: Settings.getBarPositionForScreen(screenName)
|
||||
readonly property bool isBarVertical: barPosition === "left" || barPosition === "right"
|
||||
readonly property real capsuleHeight: Style.getCapsuleHeightForScreen(screenName)
|
||||
|
||||
readonly property string displayMode: widgetSettings.displayMode !== undefined ? widgetSettings.displayMode : widgetMetadata.displayMode
|
||||
readonly property bool useGraphicMode: displayMode === "graphic" || displayMode === "graphic-clean"
|
||||
|
||||
readonly property bool hideIfNotDetected: widgetSettings.hideIfNotDetected !== undefined ? widgetSettings.hideIfNotDetected : widgetMetadata.hideIfNotDetected
|
||||
readonly property bool hideIfIdle: widgetSettings.hideIfIdle !== undefined ? widgetSettings.hideIfIdle : widgetMetadata.hideIfIdle
|
||||
|
||||
// Check if selected device is actually present/connected
|
||||
readonly property bool isReady: BatteryService.isDeviceReady(selectedDevice)
|
||||
readonly property bool isPresent: BatteryService.isDevicePresent(selectedDevice)
|
||||
readonly property real percent: isReady ? BatteryService.getPercentage(selectedDevice) : -1
|
||||
readonly property bool isCharging: isReady ? BatteryService.isCharging(selectedDevice) : false
|
||||
readonly property bool isPluggedIn: isReady ? BatteryService.isPluggedIn(selectedDevice) : false
|
||||
readonly property bool isLowBattery: isReady ? BatteryService.isLowBattery(selectedDevice) : false
|
||||
readonly property bool isCriticalBattery: isReady ? BatteryService.isCriticalBattery(selectedDevice) : false
|
||||
|
||||
// Visibility: show if hideIfNotDetected is false, or if battery is ready
|
||||
readonly property bool shouldShow: !hideIfNotDetected || (isReady && (hideIfIdle ? !isPluggedIn : true))
|
||||
readonly property string deviceNativePath: widgetSettings.deviceNativePath !== undefined ? widgetSettings.deviceNativePath : widgetMetadata.deviceNativePath
|
||||
readonly property var selectedDevice: BatteryService.isDevicePresent(BatteryService.findDevice(deviceNativePath)) ? BatteryService.findDevice(deviceNativePath) : null
|
||||
|
||||
readonly property var tooltipContent: {
|
||||
if (!isReady || !isPresent) {
|
||||
return I18n.tr("battery.no-battery-detected");
|
||||
}
|
||||
|
||||
let rows = [];
|
||||
const isInternal = selectedDevice.isLaptopBattery;
|
||||
if (isInternal) {
|
||||
// Show charge percentage
|
||||
rows.push([I18n.tr("battery.battery-level"), `${percent}%`]);
|
||||
|
||||
let timeText = BatteryService.getTimeRemainingText(selectedDevice);
|
||||
if (timeText) {
|
||||
const colonIdx = timeText.indexOf(":");
|
||||
if (colonIdx >= 0) {
|
||||
rows.push([timeText.substring(0, colonIdx).trim(), timeText.substring(colonIdx + 1).trim()]);
|
||||
} else {
|
||||
rows.push([timeText, ""]);
|
||||
}
|
||||
}
|
||||
|
||||
let rateText = BatteryService.getRateText(selectedDevice);
|
||||
if (!isPluggedIn && rateText) {
|
||||
const colonIdx = rateText.indexOf(":");
|
||||
if (colonIdx >= 0) {
|
||||
rows.push([rateText.substring(0, colonIdx).trim(), rateText.substring(colonIdx + 1).trim()]);
|
||||
} else {
|
||||
rows.push([rateText, ""]);
|
||||
}
|
||||
}
|
||||
|
||||
// Show battery health if supported (check actual battery, not DisplayDevice)
|
||||
let healthDevice = selectedDevice.healthSupported ? selectedDevice : (BatteryService.laptopBatteries.length > 0 ? BatteryService.laptopBatteries[0] : null);
|
||||
if (healthDevice && healthDevice.healthSupported) {
|
||||
rows.push([I18n.tr("battery.battery-health"), `${Math.round(healthDevice.healthPercentage)}%`]);
|
||||
}
|
||||
} else if (selectedDevice) {
|
||||
// External / Peripheral Device (Phone, Keyboard, Mouse, Gamepad, Headphone etc.)
|
||||
let name = BatteryService.getDeviceName(selectedDevice);
|
||||
rows.push([name, `${percent}%`]);
|
||||
}
|
||||
|
||||
// If we are showing the main laptop battery, append external devices
|
||||
if (isInternal) {
|
||||
var external = BatteryService.bluetoothBatteries;
|
||||
if (external.length > 0) {
|
||||
if (rows.length > 0) {
|
||||
rows.push(["---", "---"]); // Separator
|
||||
}
|
||||
for (var j = 0; j < external.length; j++) {
|
||||
var dev = external[j];
|
||||
var dName = BatteryService.getDeviceName(dev);
|
||||
var dPct = BatteryService.getPercentage(dev);
|
||||
rows.push([dName, `${dPct}%`]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
visible: shouldShow
|
||||
opacity: shouldShow ? 1.0 : 0.0
|
||||
|
||||
implicitWidth: useGraphicMode ? capsule.width : pill.width
|
||||
implicitHeight: useGraphicMode ? capsule.height : pill.height
|
||||
|
||||
NPopupContextMenu {
|
||||
id: contextMenu
|
||||
|
||||
model: [
|
||||
{
|
||||
"label": I18n.tr("actions.widget-settings"),
|
||||
"action": "widget-settings",
|
||||
"icon": "settings"
|
||||
},
|
||||
]
|
||||
|
||||
onTriggered: action => {
|
||||
contextMenu.close();
|
||||
PanelService.closeContextMenu(screen);
|
||||
|
||||
if (action === "widget-settings") {
|
||||
BarService.openWidgetSettings(screen, section, sectionWidgetIndex, widgetId, widgetSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== GRAPHIC MODE ====================
|
||||
|
||||
// Capsule background (graphic mode only)
|
||||
Rectangle {
|
||||
id: capsule
|
||||
visible: root.useGraphicMode
|
||||
anchors.centerIn: nBattery
|
||||
width: root.isBarVertical ? root.capsuleHeight : nBattery.width + Style.margin2S
|
||||
height: root.isBarVertical ? nBattery.height + Style.margin2S : root.capsuleHeight
|
||||
radius: Math.min(Style.radiusL, width / 2)
|
||||
color: graphicMouseArea.containsMouse ? Color.mHover : Style.capsuleColor
|
||||
border.color: Style.capsuleBorderColor
|
||||
border.width: Style.capsuleBorderWidth
|
||||
|
||||
Behavior on color {
|
||||
enabled: !Color.isTransitioning
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NBattery {
|
||||
id: nBattery
|
||||
visible: root.useGraphicMode
|
||||
anchors.centerIn: parent
|
||||
baseSize: (Style.getBarHeightForScreen(root.screenName) / root.capsuleHeight) * Style.fontSizeXXS
|
||||
showPercentageText: root.displayMode !== "graphic-clean"
|
||||
vertical: root.isBarVertical
|
||||
percentage: root.percent
|
||||
ready: root.isReady
|
||||
charging: root.isCharging
|
||||
pluggedIn: root.isPluggedIn
|
||||
low: root.isLowBattery
|
||||
critical: root.isCriticalBattery
|
||||
baseColor: graphicMouseArea.containsMouse ? Color.mOnHover : Color.mOnSurface
|
||||
textColor: graphicMouseArea.containsMouse ? Color.mHover : Color.mSurface
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: graphicMouseArea
|
||||
visible: root.useGraphicMode
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onEntered: {
|
||||
if (!getBatteryPanel()?.isPanelOpen && root.tooltipContent) {
|
||||
TooltipService.show(root, root.tooltipContent, BarService.getTooltipDirection(root.screen?.name));
|
||||
tooltipRefreshTimer.start();
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
tooltipRefreshTimer.stop();
|
||||
TooltipService.hide();
|
||||
}
|
||||
onClicked: mouse => {
|
||||
TooltipService.hide();
|
||||
if (mouse.button === Qt.RightButton) {
|
||||
PanelService.showContextMenu(contextMenu, nBattery, screen);
|
||||
} else {
|
||||
toggleBatteryPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: tooltipRefreshTimer
|
||||
interval: 1000
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (graphicMouseArea.containsMouse) {
|
||||
TooltipService.updateText(root.tooltipContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== ICON MODE ====================
|
||||
|
||||
BarPill {
|
||||
id: pill
|
||||
visible: !root.useGraphicMode
|
||||
screen: root.screen
|
||||
oppositeDirection: BarService.getPillDirection(root)
|
||||
icon: BatteryService.getIcon(root.percent, root.isCharging, root.isPluggedIn, root.isReady)
|
||||
text: root.isReady ? root.percent : "-"
|
||||
suffix: "%"
|
||||
autoHide: false
|
||||
forceOpen: root.isReady && root.displayMode === "icon-always"
|
||||
forceClose: root.displayMode === "icon-only" || !root.isReady
|
||||
customBackgroundColor: root.isCharging ? Color.mPrimary : ((root.isLowBattery || root.isCriticalBattery) ? Color.mError : "transparent")
|
||||
customTextIconColor: root.isCharging ? Color.mOnPrimary : ((root.isLowBattery || root.isCriticalBattery) ? Color.mOnError : "transparent")
|
||||
tooltipText: !getBatteryPanel()?.isPanelOpen ? root.tooltipContent : ""
|
||||
onClicked: toggleBatteryPanel()
|
||||
onRightClicked: PanelService.showContextMenu(contextMenu, pill, screen)
|
||||
}
|
||||
|
||||
// ==================== SHARED ====================
|
||||
|
||||
function getBatteryPanel() {
|
||||
var panel = PanelService.getPanel("batteryPanel", screen);
|
||||
if (panel) {
|
||||
panel.panelID = {
|
||||
showPowerProfiles: widgetSettings.showPowerProfiles !== undefined ? widgetSettings.showPowerProfiles : widgetMetadata.showPowerProfiles,
|
||||
showNoctaliaPerformance: widgetSettings.showNoctaliaPerformance !== undefined ? widgetSettings.showNoctaliaPerformance : widgetMetadata.showNoctaliaPerformance
|
||||
};
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
function toggleBatteryPanel() {
|
||||
getBatteryPanel()?.toggle(root);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user