1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00

dgop: use dgop for uptime

This commit is contained in:
bbedward
2025-11-28 10:41:59 -05:00
parent d3030c3ec6
commit 94a1aebe2b
8 changed files with 355 additions and 403 deletions

View File

@@ -22,7 +22,6 @@ FloatingWindow {
return;
}
visible = true;
UserInfoService.getUptime();
}
function hide() {

View File

@@ -8,16 +8,18 @@ Rectangle {
property bool editMode: false
signal powerButtonClicked()
signal lockRequested()
signal editModeToggled()
signal settingsButtonClicked()
signal powerButtonClicked
signal lockRequested
signal editModeToggled
signal settingsButtonClicked
Component.onCompleted: DgopService.addRef("system")
Component.onDestruction: DgopService.removeRef("system")
implicitHeight: 70
radius: Theme.cornerRadius
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
Theme.outline.b, 0.08)
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
Row {
@@ -34,12 +36,12 @@ Rectangle {
height: 60
imageSource: {
if (PortalService.profileImage === "")
return ""
return "";
if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage
return "file://" + PortalService.profileImage;
return PortalService.profileImage
return PortalService.profileImage;
}
fallbackIcon: "person"
}
@@ -49,14 +51,13 @@ Rectangle {
spacing: 2
Typography {
text: UserInfoService.fullName
|| UserInfoService.username || "User"
text: UserInfoService.fullName || UserInfoService.username || "User"
style: Typography.Style.Subtitle
color: Theme.surfaceText
}
Typography {
text: (UserInfoService.uptime || "Unknown")
text: DgopService.uptime || "Unknown"
style: Typography.Style.Caption
color: Theme.surfaceVariantText
}
@@ -77,7 +78,7 @@ Rectangle {
iconColor: Theme.surfaceText
backgroundColor: "transparent"
onClicked: {
root.lockRequested()
root.lockRequested();
}
}
@@ -97,8 +98,8 @@ Rectangle {
iconColor: Theme.surfaceText
backgroundColor: "transparent"
onClicked: {
root.settingsButtonClicked()
settingsModal.show()
root.settingsButtonClicked();
settingsModal.show();
}
}

View File

@@ -84,11 +84,8 @@ DankPopout {
if (shouldBeVisible) {
collapseAll();
Qt.callLater(() => {
if (NetworkService.activeService) {
if (NetworkService.activeService)
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled;
}
if (UserInfoService)
UserInfoService.getUptime();
});
} else {
Qt.callLater(() => {

View File

@@ -1,5 +1,4 @@
import QtQuick
import QtQuick.Effects
import qs.Common
import qs.Services
import qs.Widgets
@@ -7,6 +6,9 @@ import qs.Widgets
Card {
id: root
Component.onCompleted: DgopService.addRef("system")
Component.onDestruction: DgopService.removeRef("system")
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
@@ -21,12 +23,12 @@ Card {
anchors.verticalCenter: parent.verticalCenter
imageSource: {
if (PortalService.profileImage === "")
return ""
return "";
if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage
return "file://" + PortalService.profileImage;
return PortalService.profileImage
return PortalService.profileImage;
}
fallbackIcon: "person"
}
@@ -56,12 +58,16 @@ Card {
StyledText {
text: {
if (CompositorService.isNiri) return "on niri"
if (CompositorService.isHyprland) return "on Hyprland"
if (CompositorService.isNiri)
return "on niri";
if (CompositorService.isHyprland)
return "on Hyprland";
// technically they might not be on mangowc, but its what we support in the docs
if (CompositorService.isDwl) return "on MangoWC"
if (CompositorService.isSway) return "on Sway"
return ""
if (CompositorService.isDwl)
return "on MangoWC";
if (CompositorService.isSway)
return "on Sway";
return "";
}
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
@@ -82,27 +88,10 @@ Card {
}
StyledText {
id: uptimeText
property real availableWidth: parent.parent.parent.parent.width - avatarContainer.width - Theme.spacingM * 3 - 16 - Theme.spacingS
property real longTextWidth: {
const fontSize = Math.round(Theme.fontSizeSmall || 12)
const testMetrics = Qt.createQmlObject('import QtQuick; TextMetrics { font.pixelSize: ' + fontSize + ' }', uptimeText)
testMetrics.text = UserInfoService.uptime || "up 1 hour, 23 minutes"
const result = testMetrics.width
testMetrics.destroy()
return result
}
// Just using truncated is always true initially idk
property bool shouldUseShort: longTextWidth > availableWidth
text: shouldUseShort ? UserInfoService.shortUptime : UserInfoService.uptime || "up 1h 23m"
text: DgopService.shortUptime || "up"
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
width: availableWidth
wrapMode: Text.NoWrap
}
}
}

View File

@@ -38,7 +38,7 @@ Item {
}
WeatherService.addRef();
UserInfoService.refreshUserInfo();
UserInfoService.getUserInfo();
if (CompositorService.isHyprland) {
updateHyprlandLayout();

View File

@@ -1,5 +1,4 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Services
import qs.Widgets
@@ -69,7 +68,7 @@ DankFlickable {
}
StyledText {
text: `${UserInfoService.uptime} Boot: ${DgopService.bootTime}`
text: `${DgopService.uptime} Boot: ${DgopService.bootTime}`
font.pixelSize: Theme.fontSizeSmall
font.family: SettingsData.monoFontFamily
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
@@ -83,9 +82,7 @@ DankFlickable {
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle {
@@ -134,7 +131,6 @@ DankFlickable {
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
@@ -181,9 +177,7 @@ DankFlickable {
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
}
Rectangle {
@@ -275,7 +269,6 @@ DankFlickable {
color: Theme.secondary
anchors.verticalCenter: parent.verticalCenter
}
}
StyledText {
@@ -365,22 +358,16 @@ DankFlickable {
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
}
Rectangle {
@@ -418,7 +405,6 @@ DankFlickable {
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
}
Column {
@@ -495,7 +481,6 @@ DankFlickable {
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
}
Repeater {
@@ -596,19 +581,11 @@ DankFlickable {
anchors.verticalCenter: parent.verticalCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
}
}
}
}
}

View File

@@ -1,5 +1,4 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
@@ -72,6 +71,8 @@ Singleton {
property string bootTime: ""
property string motherboard: ""
property string biosVersion: ""
property string uptime: ""
property string shortUptime: ""
property int historySize: 60
property var cpuHistory: []
@@ -86,310 +87,310 @@ Singleton {
})
function addRef(modules = null) {
refCount++
let modulesChanged = false
refCount++;
let modulesChanged = false;
if (modules) {
const modulesToAdd = Array.isArray(modules) ? modules : [modules]
const modulesToAdd = Array.isArray(modules) ? modules : [modules];
for (const module of modulesToAdd) {
// Increment reference count for this module
const currentCount = moduleRefCounts[module] || 0
moduleRefCounts[module] = currentCount + 1
console.log("Adding ref for module:", module, "count:", moduleRefCounts[module])
const currentCount = moduleRefCounts[module] || 0;
moduleRefCounts[module] = currentCount + 1;
console.log("Adding ref for module:", module, "count:", moduleRefCounts[module]);
// Add to enabled modules if not already there
if (enabledModules.indexOf(module) === -1) {
enabledModules.push(module)
modulesChanged = true
enabledModules.push(module);
modulesChanged = true;
}
}
}
if (modulesChanged || refCount === 1) {
enabledModules = enabledModules.slice() // Force property change
moduleRefCounts = Object.assign({}, moduleRefCounts) // Force property change
updateAllStats()
enabledModules = enabledModules.slice(); // Force property change
moduleRefCounts = Object.assign({}, moduleRefCounts); // Force property change
updateAllStats();
} else if (gpuPciIds.length > 0 && refCount > 0) {
// If we have GPU PCI IDs and active modules, make sure to update
// This handles the case where PCI IDs were loaded after modules were added
updateAllStats()
updateAllStats();
}
}
function removeRef(modules = null) {
refCount = Math.max(0, refCount - 1)
let modulesChanged = false
refCount = Math.max(0, refCount - 1);
let modulesChanged = false;
if (modules) {
const modulesToRemove = Array.isArray(modules) ? modules : [modules]
const modulesToRemove = Array.isArray(modules) ? modules : [modules];
for (const module of modulesToRemove) {
const currentCount = moduleRefCounts[module] || 0
const currentCount = moduleRefCounts[module] || 0;
if (currentCount > 1) {
// Decrement reference count
moduleRefCounts[module] = currentCount - 1
console.log("Removing ref for module:", module, "count:", moduleRefCounts[module])
moduleRefCounts[module] = currentCount - 1;
console.log("Removing ref for module:", module, "count:", moduleRefCounts[module]);
} else if (currentCount === 1) {
// Remove completely when count reaches 0
delete moduleRefCounts[module]
const index = enabledModules.indexOf(module)
delete moduleRefCounts[module];
const index = enabledModules.indexOf(module);
if (index > -1) {
enabledModules.splice(index, 1)
modulesChanged = true
console.log("Disabling module:", module, "(no more refs)")
enabledModules.splice(index, 1);
modulesChanged = true;
console.log("Disabling module:", module, "(no more refs)");
}
}
}
}
if (modulesChanged) {
enabledModules = enabledModules.slice() // Force property change
moduleRefCounts = Object.assign({}, moduleRefCounts) // Force property change
enabledModules = enabledModules.slice(); // Force property change
moduleRefCounts = Object.assign({}, moduleRefCounts); // Force property change
// Clear cursor data when CPU or process modules are no longer active
if (!enabledModules.includes("cpu")) {
cpuCursor = ""
cpuSampleCount = 0
cpuCursor = "";
cpuSampleCount = 0;
}
if (!enabledModules.includes("processes")) {
procCursor = ""
processSampleCount = 0
procCursor = "";
processSampleCount = 0;
}
}
}
function setGpuPciIds(pciIds) {
gpuPciIds = Array.isArray(pciIds) ? pciIds : []
gpuPciIds = Array.isArray(pciIds) ? pciIds : [];
}
function addGpuPciId(pciId) {
const currentCount = gpuPciIdRefCounts[pciId] || 0
gpuPciIdRefCounts[pciId] = currentCount + 1
const currentCount = gpuPciIdRefCounts[pciId] || 0;
gpuPciIdRefCounts[pciId] = currentCount + 1;
// Add to gpuPciIds array if not already there
if (!gpuPciIds.includes(pciId)) {
gpuPciIds = gpuPciIds.concat([pciId])
gpuPciIds = gpuPciIds.concat([pciId]);
}
console.log("Adding GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId])
console.log("Adding GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId]);
// Force property change notification
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts)
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
}
function removeGpuPciId(pciId) {
const currentCount = gpuPciIdRefCounts[pciId] || 0
const currentCount = gpuPciIdRefCounts[pciId] || 0;
if (currentCount > 1) {
// Decrement reference count
gpuPciIdRefCounts[pciId] = currentCount - 1
console.log("Removing GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId])
gpuPciIdRefCounts[pciId] = currentCount - 1;
console.log("Removing GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId]);
} else if (currentCount === 1) {
// Remove completely when count reaches 0
delete gpuPciIdRefCounts[pciId]
const index = gpuPciIds.indexOf(pciId)
delete gpuPciIdRefCounts[pciId];
const index = gpuPciIds.indexOf(pciId);
if (index > -1) {
gpuPciIds = gpuPciIds.slice()
gpuPciIds.splice(index, 1)
gpuPciIds = gpuPciIds.slice();
gpuPciIds.splice(index, 1);
}
// Clear temperature data for this GPU when no longer monitored
if (availableGpus && availableGpus.length > 0) {
const updatedGpus = availableGpus.slice()
const updatedGpus = availableGpus.slice();
for (var i = 0; i < updatedGpus.length; i++) {
if (updatedGpus[i].pciId === pciId) {
updatedGpus[i] = Object.assign({}, updatedGpus[i], {
"temperature": 0
})
});
}
}
availableGpus = updatedGpus
availableGpus = updatedGpus;
}
console.log("Removing GPU PCI ID completely:", pciId)
console.log("Removing GPU PCI ID completely:", pciId);
}
// Force property change notification
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts)
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
}
function setProcessOptions(limit = 20, sort = "cpu", disableCpu = false) {
processLimit = limit
processSort = sort
noCpu = disableCpu
processLimit = limit;
processSort = sort;
noCpu = disableCpu;
}
function updateAllStats() {
if (dgopAvailable && refCount > 0 && enabledModules.length > 0) {
isUpdating = true
dgopProcess.running = true
isUpdating = true;
dgopProcess.running = true;
} else {
isUpdating = false
isUpdating = false;
}
}
function initializeGpuMetadata() {
if (!dgopAvailable)
return
gpuInitProcess.running = true
return;
gpuInitProcess.running = true;
}
function initializeSystemMetadata() {
if (!dgopAvailable)
return
systemInitProcess.running = true
return;
systemInitProcess.running = true;
}
function buildDgopCommand() {
const cmd = ["dgop", "meta", "--json"]
const cmd = ["dgop", "meta", "--json"];
if (enabledModules.length === 0) {
// Don't run if no modules are needed
return []
return [];
}
// Replace 'gpu' with 'gpu-temp' when we have PCI IDs to monitor
const finalModules = []
const finalModules = [];
for (const module of enabledModules) {
if (module === "gpu" && gpuPciIds.length > 0) {
finalModules.push("gpu-temp")
finalModules.push("gpu-temp");
} else if (module !== "gpu") {
finalModules.push(module)
finalModules.push(module);
}
}
// Add gpu-temp module automatically when we have PCI IDs to monitor
if (gpuPciIds.length > 0 && finalModules.indexOf("gpu-temp") === -1) {
finalModules.push("gpu-temp")
finalModules.push("gpu-temp");
}
if (enabledModules.indexOf("all") !== -1) {
cmd.push("--modules", "all")
cmd.push("--modules", "all");
} else if (finalModules.length > 0) {
const moduleList = finalModules.join(",")
cmd.push("--modules", moduleList)
const moduleList = finalModules.join(",");
cmd.push("--modules", moduleList);
} else {
return []
return [];
}
// Add cursor data if available for accurate CPU percentages
if ((enabledModules.includes("cpu") || enabledModules.includes("all")) && cpuCursor) {
cmd.push("--cpu-cursor", cpuCursor)
cmd.push("--cpu-cursor", cpuCursor);
}
if ((enabledModules.includes("processes") || enabledModules.includes("all")) && procCursor) {
cmd.push("--proc-cursor", procCursor)
cmd.push("--proc-cursor", procCursor);
}
if (gpuPciIds.length > 0) {
cmd.push("--gpu-pci-ids", gpuPciIds.join(","))
cmd.push("--gpu-pci-ids", gpuPciIds.join(","));
}
if (enabledModules.indexOf("processes") !== -1 || enabledModules.indexOf("all") !== -1) {
cmd.push("--limit", "100") // Get more data for client sorting
cmd.push("--sort", "cpu") // Always get CPU sorted data
cmd.push("--limit", "100"); // Get more data for client sorting
cmd.push("--sort", "cpu"); // Always get CPU sorted data
if (noCpu) {
cmd.push("--no-cpu")
cmd.push("--no-cpu");
}
}
return cmd
return cmd;
}
function parseData(data) {
if (data.cpu) {
const cpu = data.cpu
cpuSampleCount++
const cpu = data.cpu;
cpuSampleCount++;
cpuUsage = cpu.usage || 0
cpuFrequency = cpu.frequency || 0
cpuTemperature = cpu.temperature || 0
cpuCores = cpu.count || 1
cpuModel = cpu.model || ""
perCoreCpuUsage = cpu.coreUsage || []
addToHistory(cpuHistory, cpuUsage)
cpuUsage = cpu.usage || 0;
cpuFrequency = cpu.frequency || 0;
cpuTemperature = cpu.temperature || 0;
cpuCores = cpu.count || 1;
cpuModel = cpu.model || "";
perCoreCpuUsage = cpu.coreUsage || [];
addToHistory(cpuHistory, cpuUsage);
if (cpu.cursor) {
cpuCursor = cpu.cursor
cpuCursor = cpu.cursor;
}
}
if (data.memory) {
const mem = data.memory
const totalKB = mem.total || 0
const availableKB = mem.available || 0
const freeKB = mem.free || 0
const mem = data.memory;
const totalKB = mem.total || 0;
const availableKB = mem.available || 0;
const freeKB = mem.free || 0;
totalMemoryMB = totalKB / 1024
availableMemoryMB = availableKB / 1024
freeMemoryMB = freeKB / 1024
usedMemoryMB = totalMemoryMB - availableMemoryMB
memoryUsage = totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0
totalMemoryMB = totalKB / 1024;
availableMemoryMB = availableKB / 1024;
freeMemoryMB = freeKB / 1024;
usedMemoryMB = totalMemoryMB - availableMemoryMB;
memoryUsage = totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0;
totalMemoryKB = totalKB
usedMemoryKB = totalKB - availableKB
totalSwapKB = mem.swaptotal || 0
usedSwapKB = (mem.swaptotal || 0) - (mem.swapfree || 0)
totalMemoryKB = totalKB;
usedMemoryKB = totalKB - availableKB;
totalSwapKB = mem.swaptotal || 0;
usedSwapKB = (mem.swaptotal || 0) - (mem.swapfree || 0);
addToHistory(memoryHistory, memoryUsage)
addToHistory(memoryHistory, memoryUsage);
}
if (data.network && Array.isArray(data.network)) {
networkInterfaces = data.network
networkInterfaces = data.network;
let totalRx = 0
let totalTx = 0
let totalRx = 0;
let totalTx = 0;
for (const iface of data.network) {
totalRx += iface.rx || 0
totalTx += iface.tx || 0
totalRx += iface.rx || 0;
totalTx += iface.tx || 0;
}
if (lastNetworkStats) {
const timeDiff = updateInterval / 1000
const rxDiff = totalRx - lastNetworkStats.rx
const txDiff = totalTx - lastNetworkStats.tx
networkRxRate = Math.max(0, rxDiff / timeDiff)
networkTxRate = Math.max(0, txDiff / timeDiff)
addToHistory(networkHistory.rx, networkRxRate / 1024)
addToHistory(networkHistory.tx, networkTxRate / 1024)
const timeDiff = updateInterval / 1000;
const rxDiff = totalRx - lastNetworkStats.rx;
const txDiff = totalTx - lastNetworkStats.tx;
networkRxRate = Math.max(0, rxDiff / timeDiff);
networkTxRate = Math.max(0, txDiff / timeDiff);
addToHistory(networkHistory.rx, networkRxRate / 1024);
addToHistory(networkHistory.tx, networkTxRate / 1024);
}
lastNetworkStats = {
"rx": totalRx,
"tx": totalTx
}
};
}
if (data.disk && Array.isArray(data.disk)) {
diskDevices = data.disk
diskDevices = data.disk;
let totalRead = 0
let totalWrite = 0
let totalRead = 0;
let totalWrite = 0;
for (const disk of data.disk) {
totalRead += (disk.read || 0) * 512
totalWrite += (disk.write || 0) * 512
totalRead += (disk.read || 0) * 512;
totalWrite += (disk.write || 0) * 512;
}
if (lastDiskStats) {
const timeDiff = updateInterval / 1000
const readDiff = totalRead - lastDiskStats.read
const writeDiff = totalWrite - lastDiskStats.write
diskReadRate = Math.max(0, readDiff / timeDiff)
diskWriteRate = Math.max(0, writeDiff / timeDiff)
addToHistory(diskHistory.read, diskReadRate / (1024 * 1024))
addToHistory(diskHistory.write, diskWriteRate / (1024 * 1024))
const timeDiff = updateInterval / 1000;
const readDiff = totalRead - lastDiskStats.read;
const writeDiff = totalWrite - lastDiskStats.write;
diskReadRate = Math.max(0, readDiff / timeDiff);
diskWriteRate = Math.max(0, writeDiff / timeDiff);
addToHistory(diskHistory.read, diskReadRate / (1024 * 1024));
addToHistory(diskHistory.write, diskWriteRate / (1024 * 1024));
}
lastDiskStats = {
"read": totalRead,
"write": totalWrite
}
};
}
if (data.diskmounts) {
diskMounts = data.diskmounts || []
diskMounts = data.diskmounts || [];
}
if (data.processes && Array.isArray(data.processes)) {
const newProcesses = []
processSampleCount++
const newProcesses = [];
processSampleCount++;
for (const proc of data.processes) {
const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0
const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0;
newProcesses.push({
"pid": proc.pid || 0,
@@ -400,39 +401,39 @@ Singleton {
"command": proc.command || "",
"fullCommand": proc.fullCommand || "",
"displayName": (proc.command && proc.command.length > 15) ? proc.command.substring(0, 15) + "..." : (proc.command || "")
})
});
}
allProcesses = newProcesses
applySorting()
allProcesses = newProcesses;
applySorting();
if (data.cursor) {
procCursor = data.cursor
procCursor = data.cursor;
}
}
const gpuData = (data.gpu && data.gpu.gpus) || data.gpus
const gpuData = (data.gpu && data.gpu.gpus) || data.gpus;
if (gpuData && Array.isArray(gpuData)) {
// Check if this is temperature update data (has PCI IDs being monitored)
if (gpuPciIds.length > 0 && availableGpus && availableGpus.length > 0) {
// This is temperature data - merge with existing GPU metadata
const updatedGpus = availableGpus.slice()
const updatedGpus = availableGpus.slice();
for (var i = 0; i < updatedGpus.length; i++) {
const existingGpu = updatedGpus[i]
const tempGpu = gpuData.find(g => g.pciId === existingGpu.pciId)
const existingGpu = updatedGpus[i];
const tempGpu = gpuData.find(g => g.pciId === existingGpu.pciId);
// Only update temperature if this GPU's PCI ID is being monitored
if (tempGpu && gpuPciIds.includes(existingGpu.pciId)) {
updatedGpus[i] = Object.assign({}, existingGpu, {
"temperature": tempGpu.temperature || 0
})
});
}
}
availableGpus = updatedGpus
availableGpus = updatedGpus;
} else {
// This is initial GPU metadata - set the full list
const gpuList = []
const gpuList = [];
for (const gpu of gpuData) {
let displayName = gpu.displayName || gpu.name || "Unknown GPU"
let fullName = gpu.fullName || gpu.name || "Unknown GPU"
let displayName = gpu.displayName || gpu.name || "Unknown GPU";
let fullName = gpu.fullName || gpu.name || "Unknown GPU";
gpuList.push({
"driver": gpu.driver || "",
@@ -441,135 +442,176 @@ Singleton {
"fullName": fullName,
"pciId": gpu.pciId || "",
"temperature": gpu.temperature || 0
})
});
}
availableGpus = gpuList
availableGpus = gpuList;
}
}
if (data.system) {
const sys = data.system
loadAverage = sys.loadavg || ""
processCount = sys.processes || 0
threadCount = sys.threads || 0
bootTime = sys.boottime || ""
const sys = data.system;
loadAverage = sys.loadavg || "";
processCount = sys.processes || 0;
threadCount = sys.threads || 0;
bootTime = sys.boottime || "";
updateUptime();
}
const hwData = data.hardware || (data.hostname || data.kernel || data.distro || data.arch) ? data : null
const hwData = data.hardware || (data.hostname || data.kernel || data.distro || data.arch) ? data : null;
if (hwData) {
hostname = hwData.hostname || ""
kernelVersion = hwData.kernel || ""
distribution = hwData.distro || ""
architecture = hwData.arch || ""
motherboard = (hwData.bios && hwData.bios.motherboard) || ""
biosVersion = (hwData.bios && hwData.bios.version) || ""
hostname = hwData.hostname || "";
kernelVersion = hwData.kernel || "";
distribution = hwData.distro || "";
architecture = hwData.arch || "";
motherboard = (hwData.bios && hwData.bios.motherboard) || "";
biosVersion = (hwData.bios && hwData.bios.version) || "";
}
isUpdating = false
isUpdating = false;
}
function addToHistory(array, value) {
array.push(value)
array.push(value);
if (array.length > historySize) {
array.shift()
array.shift();
}
}
function getProcessIcon(command) {
const cmd = command.toLowerCase()
const cmd = command.toLowerCase();
if (cmd.includes("firefox") || cmd.includes("chrome") || cmd.includes("browser") || cmd.includes("chromium")) {
return "web"
return "web";
}
if (cmd.includes("code") || cmd.includes("editor") || cmd.includes("vim")) {
return "code"
return "code";
}
if (cmd.includes("terminal") || cmd.includes("bash") || cmd.includes("zsh")) {
return "terminal"
return "terminal";
}
if (cmd.includes("music") || cmd.includes("audio") || cmd.includes("spotify")) {
return "music_note"
return "music_note";
}
if (cmd.includes("video") || cmd.includes("vlc") || cmd.includes("mpv")) {
return "play_circle"
return "play_circle";
}
if (cmd.includes("systemd") || cmd.includes("elogind") || cmd.includes("kernel") || cmd.includes("kthread") || cmd.includes("kworker")) {
return "settings"
return "settings";
}
return "memory"
return "memory";
}
function formatCpuUsage(cpu) {
return (cpu || 0).toFixed(1) + "%"
return (cpu || 0).toFixed(1) + "%";
}
function formatMemoryUsage(memoryKB) {
const mem = memoryKB || 0
const mem = memoryKB || 0;
if (mem < 1024) {
return mem.toFixed(0) + " KB"
return mem.toFixed(0) + " KB";
} else if (mem < 1024 * 1024) {
return (mem / 1024).toFixed(1) + " MB"
return (mem / 1024).toFixed(1) + " MB";
} else {
return (mem / (1024 * 1024)).toFixed(1) + " GB"
return (mem / (1024 * 1024)).toFixed(1) + " GB";
}
}
function formatSystemMemory(memoryKB) {
const mem = memoryKB || 0
const mem = memoryKB || 0;
if (mem === 0) {
return "--"
return "--";
}
if (mem < 1024 * 1024) {
return (mem / 1024).toFixed(0) + " MB"
return (mem / 1024).toFixed(0) + " MB";
} else {
return (mem / (1024 * 1024)).toFixed(1) + " GB"
return (mem / (1024 * 1024)).toFixed(1) + " GB";
}
}
function killProcess(pid) {
if (pid > 0) {
Quickshell.execDetached("kill", [pid.toString()])
Quickshell.execDetached("kill", [pid.toString()]);
}
}
function updateUptime() {
if (!bootTime) {
uptime = "";
shortUptime = "";
return;
}
const bootDate = new Date(bootTime.replace(" ", "T"));
if (isNaN(bootDate.getTime())) {
uptime = "";
shortUptime = "";
return;
}
const now = new Date();
const seconds = Math.floor((now - bootDate) / 1000);
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const parts = [];
if (days > 0)
parts.push(`${days} day${days === 1 ? "" : "s"}`);
if (hours > 0)
parts.push(`${hours} hour${hours === 1 ? "" : "s"}`);
if (minutes > 0)
parts.push(`${minutes} minute${minutes === 1 ? "" : "s"}`);
uptime = parts.length > 0 ? `up ${parts.join(", ")}` : `up ${seconds} seconds`;
var shortStr = "up";
if (days > 0)
shortStr += ` ${days}d`;
if (hours > 0)
shortStr += ` ${hours}h`;
if (minutes > 0)
shortStr += ` ${minutes}m`;
shortUptime = shortStr;
}
function setSortBy(newSortBy) {
if (newSortBy !== currentSort) {
currentSort = newSortBy
applySorting()
currentSort = newSortBy;
applySorting();
}
}
function applySorting() {
if (!allProcesses || allProcesses.length === 0) {
return
return;
}
const sorted = allProcesses.slice()
const sorted = allProcesses.slice();
sorted.sort((a, b) => {
let valueA, valueB
let valueA, valueB;
switch (currentSort) {
case "cpu":
valueA = a.cpu || 0
valueB = b.cpu || 0
return valueB - valueA
valueA = a.cpu || 0;
valueB = b.cpu || 0;
return valueB - valueA;
case "memory":
valueA = a.memoryKB || 0
valueB = b.memoryKB || 0
return valueB - valueA
valueA = a.memoryKB || 0;
valueB = b.memoryKB || 0;
return valueB - valueA;
case "name":
valueA = (a.command || "").toLowerCase()
valueB = (b.command || "").toLowerCase()
return valueA.localeCompare(valueB)
valueA = (a.command || "").toLowerCase();
valueB = (b.command || "").toLowerCase();
return valueA.localeCompare(valueB);
case "pid":
valueA = a.pid || 0
valueB = b.pid || 0
return valueA - valueB
valueA = a.pid || 0;
valueB = b.pid || 0;
return valueA - valueB;
default:
return 0
return 0;
}
})
});
processes = sorted.slice(0, processLimit)
processes = sorted.slice(0, processLimit);
}
Timer {
@@ -585,26 +627,26 @@ Singleton {
id: dgopProcess
command: root.buildDgopCommand()
running: false
onCommandChanged: {
onCommandChanged:
//console.log("DgopService command:", JSON.stringify(command))
}
{}
onExited: exitCode => {
if (exitCode !== 0) {
console.warn("Dgop process failed with exit code:", exitCode)
isUpdating = false
console.warn("Dgop process failed with exit code:", exitCode);
isUpdating = false;
}
}
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
try {
const data = JSON.parse(text.trim())
parseData(data)
const data = JSON.parse(text.trim());
parseData(data);
} catch (e) {
console.warn("Failed to parse dgop JSON:", e)
console.warn("Raw text was:", text.substring(0, 200))
isUpdating = false
console.warn("Failed to parse dgop JSON:", e);
console.warn("Raw text was:", text.substring(0, 200));
isUpdating = false;
}
}
}
@@ -617,17 +659,17 @@ Singleton {
running: false
onExited: exitCode => {
if (exitCode !== 0) {
console.warn("GPU init process failed with exit code:", exitCode)
console.warn("GPU init process failed with exit code:", exitCode);
}
}
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
try {
const data = JSON.parse(text.trim())
parseData(data)
const data = JSON.parse(text.trim());
parseData(data);
} catch (e) {
console.warn("Failed to parse GPU init JSON:", e)
console.warn("Failed to parse GPU init JSON:", e);
}
}
}
@@ -640,17 +682,17 @@ Singleton {
running: false
onExited: exitCode => {
if (exitCode !== 0) {
console.warn("System init process failed with exit code:", exitCode)
console.warn("System init process failed with exit code:", exitCode);
}
}
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
try {
const data = JSON.parse(text.trim())
parseData(data)
const data = JSON.parse(text.trim());
parseData(data);
} catch (e) {
console.warn("Failed to parse system init JSON:", e)
console.warn("Failed to parse system init JSON:", e);
}
}
}
@@ -662,20 +704,20 @@ Singleton {
command: ["which", "dgop"]
running: false
onExited: exitCode => {
dgopAvailable = (exitCode === 0)
dgopAvailable = (exitCode === 0);
if (dgopAvailable) {
initializeGpuMetadata()
initializeSystemMetadata()
initializeGpuMetadata();
initializeSystemMetadata();
if (SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.length > 0) {
for (const pciId of SessionData.enabledGpuPciIds) {
addGpuPciId(pciId)
addGpuPciId(pciId);
}
if (refCount > 0 && enabledModules.length > 0) {
updateAllStats()
updateAllStats();
}
}
} else {
console.warn("dgop is not installed or not in PATH")
console.warn("dgop is not installed or not in PATH");
}
}
}
@@ -686,33 +728,33 @@ Singleton {
running: false
onExited: exitCode => {
if (exitCode !== 0) {
console.warn("Failed to read /etc/os-release")
console.warn("Failed to read /etc/os-release");
}
}
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
try {
const lines = text.trim().split('\n')
let prettyName = ""
let name = ""
const lines = text.trim().split('\n');
let prettyName = "";
let name = "";
for (const line of lines) {
const trimmedLine = line.trim()
const trimmedLine = line.trim();
if (trimmedLine.startsWith('PRETTY_NAME=')) {
prettyName = trimmedLine.substring(12).replace(/^["']|["']$/g, '')
prettyName = trimmedLine.substring(12).replace(/^["']|["']$/g, '');
} else if (trimmedLine.startsWith('NAME=')) {
name = trimmedLine.substring(5).replace(/^["']|["']$/g, '')
name = trimmedLine.substring(5).replace(/^["']|["']$/g, '');
}
}
// Prefer PRETTY_NAME, fallback to NAME
const distroName = prettyName || name || "Linux"
distribution = distroName
console.info("Detected distribution:", distroName)
const distroName = prettyName || name || "Linux";
distribution = distroName;
console.info("Detected distribution:", distroName);
} catch (e) {
console.warn("Failed to parse /etc/os-release:", e)
distribution = "Linux"
console.warn("Failed to parse /etc/os-release:", e);
distribution = "Linux";
}
}
}
@@ -720,7 +762,7 @@ Singleton {
}
Component.onCompleted: {
dgopCheckProcess.running = true
osReleaseProcess.running = true
dgopCheckProcess.running = true;
osReleaseProcess.running = true;
}
}

View File

@@ -1,5 +1,4 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
@@ -12,77 +11,25 @@ Singleton {
property string username: ""
property string fullName: ""
property string profilePicture: ""
property string uptime: ""
property string shortUptime: ""
property string hostname: ""
property bool profileAvailable: false
function getUserInfo() {
Proc.runCommand("userInfo", ["bash", "-c", "echo \"$USER|$(getent passwd $USER | cut -d: -f5 | cut -d, -f1)|$(hostname)\""], (output, exitCode) => {
Proc.runCommand("userInfo", ["sh", "-c", "echo \"$USER|$(getent passwd $USER | cut -d: -f5 | cut -d, -f1)|$(hostname)\""], (output, exitCode) => {
if (exitCode !== 0) {
root.username = "User"
root.fullName = "User"
root.hostname = "System"
return
root.username = "User";
root.fullName = "User";
root.hostname = "System";
return;
}
const parts = output.trim().split("|")
const parts = output.trim().split("|");
if (parts.length >= 3) {
root.username = parts[0] || ""
root.fullName = parts[1] || parts[0] || ""
root.hostname = parts[2] || ""
root.username = parts[0] || "";
root.fullName = parts[1] || parts[0] || "";
root.hostname = parts[2] || "";
}
}, 0)
}, 0);
}
function getUptime() {
Proc.runCommand("uptime", ["cat", "/proc/uptime"], (output, exitCode) => {
if (exitCode !== 0) {
root.uptime = "Unknown"
return
}
const seconds = parseInt(output.split(" ")[0])
const days = Math.floor(seconds / 86400)
const hours = Math.floor((seconds % 86400) / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
const parts = []
if (days > 0) {
parts.push(`${days} day${days === 1 ? "" : "s"}`)
}
if (hours > 0) {
parts.push(`${hours} hour${hours === 1 ? "" : "s"}`)
}
if (minutes > 0) {
parts.push(`${minutes} minute${minutes === 1 ? "" : "s"}`)
}
if (parts.length > 0) {
root.uptime = `up ${parts.join(", ")}`
} else {
root.uptime = `up ${seconds} seconds`
}
let shortUptime = "up"
if (days > 0) {
shortUptime += ` ${days}d`
}
if (hours > 0) {
shortUptime += ` ${hours}h`
}
if (minutes > 0) {
shortUptime += ` ${minutes}m`
}
root.shortUptime = shortUptime
}, 0)
}
function refreshUserInfo() {
getUserInfo()
getUptime()
}
Component.onCompleted: {
getUserInfo()
getUptime()
}
Component.onCompleted: getUserInfo()
}