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:
@@ -22,7 +22,6 @@ FloatingWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visible = true;
|
visible = true;
|
||||||
UserInfoService.getUptime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
|
|||||||
@@ -8,16 +8,18 @@ Rectangle {
|
|||||||
|
|
||||||
property bool editMode: false
|
property bool editMode: false
|
||||||
|
|
||||||
signal powerButtonClicked()
|
signal powerButtonClicked
|
||||||
signal lockRequested()
|
signal lockRequested
|
||||||
signal editModeToggled()
|
signal editModeToggled
|
||||||
signal settingsButtonClicked()
|
signal settingsButtonClicked
|
||||||
|
|
||||||
|
Component.onCompleted: DgopService.addRef("system")
|
||||||
|
Component.onDestruction: DgopService.removeRef("system")
|
||||||
|
|
||||||
implicitHeight: 70
|
implicitHeight: 70
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g,
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
Theme.outline.b, 0.08)
|
|
||||||
border.width: 0
|
border.width: 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
@@ -34,12 +36,12 @@ Rectangle {
|
|||||||
height: 60
|
height: 60
|
||||||
imageSource: {
|
imageSource: {
|
||||||
if (PortalService.profileImage === "")
|
if (PortalService.profileImage === "")
|
||||||
return ""
|
return "";
|
||||||
|
|
||||||
if (PortalService.profileImage.startsWith("/"))
|
if (PortalService.profileImage.startsWith("/"))
|
||||||
return "file://" + PortalService.profileImage
|
return "file://" + PortalService.profileImage;
|
||||||
|
|
||||||
return PortalService.profileImage
|
return PortalService.profileImage;
|
||||||
}
|
}
|
||||||
fallbackIcon: "person"
|
fallbackIcon: "person"
|
||||||
}
|
}
|
||||||
@@ -49,14 +51,13 @@ Rectangle {
|
|||||||
spacing: 2
|
spacing: 2
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: UserInfoService.fullName
|
text: UserInfoService.fullName || UserInfoService.username || "User"
|
||||||
|| UserInfoService.username || "User"
|
|
||||||
style: Typography.Style.Subtitle
|
style: Typography.Style.Subtitle
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
}
|
}
|
||||||
|
|
||||||
Typography {
|
Typography {
|
||||||
text: (UserInfoService.uptime || "Unknown")
|
text: DgopService.uptime || "Unknown"
|
||||||
style: Typography.Style.Caption
|
style: Typography.Style.Caption
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,7 @@ Rectangle {
|
|||||||
iconColor: Theme.surfaceText
|
iconColor: Theme.surfaceText
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.lockRequested()
|
root.lockRequested();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +98,8 @@ Rectangle {
|
|||||||
iconColor: Theme.surfaceText
|
iconColor: Theme.surfaceText
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.settingsButtonClicked()
|
root.settingsButtonClicked();
|
||||||
settingsModal.show()
|
settingsModal.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,11 +84,8 @@ DankPopout {
|
|||||||
if (shouldBeVisible) {
|
if (shouldBeVisible) {
|
||||||
collapseAll();
|
collapseAll();
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
if (NetworkService.activeService) {
|
if (NetworkService.activeService)
|
||||||
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled;
|
NetworkService.activeService.autoRefreshEnabled = NetworkService.wifiEnabled;
|
||||||
}
|
|
||||||
if (UserInfoService)
|
|
||||||
UserInfoService.getUptime();
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Qt.callLater(() => {
|
Qt.callLater(() => {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
@@ -7,6 +6,9 @@ import qs.Widgets
|
|||||||
Card {
|
Card {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
Component.onCompleted: DgopService.addRef("system")
|
||||||
|
Component.onDestruction: DgopService.removeRef("system")
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: Theme.spacingM
|
anchors.leftMargin: Theme.spacingM
|
||||||
@@ -21,12 +23,12 @@ Card {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
imageSource: {
|
imageSource: {
|
||||||
if (PortalService.profileImage === "")
|
if (PortalService.profileImage === "")
|
||||||
return ""
|
return "";
|
||||||
|
|
||||||
if (PortalService.profileImage.startsWith("/"))
|
if (PortalService.profileImage.startsWith("/"))
|
||||||
return "file://" + PortalService.profileImage
|
return "file://" + PortalService.profileImage;
|
||||||
|
|
||||||
return PortalService.profileImage
|
return PortalService.profileImage;
|
||||||
}
|
}
|
||||||
fallbackIcon: "person"
|
fallbackIcon: "person"
|
||||||
}
|
}
|
||||||
@@ -56,12 +58,16 @@ Card {
|
|||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: {
|
text: {
|
||||||
if (CompositorService.isNiri) return "on niri"
|
if (CompositorService.isNiri)
|
||||||
if (CompositorService.isHyprland) return "on Hyprland"
|
return "on niri";
|
||||||
|
if (CompositorService.isHyprland)
|
||||||
|
return "on Hyprland";
|
||||||
// technically they might not be on mangowc, but its what we support in the docs
|
// technically they might not be on mangowc, but its what we support in the docs
|
||||||
if (CompositorService.isDwl) return "on MangoWC"
|
if (CompositorService.isDwl)
|
||||||
if (CompositorService.isSway) return "on Sway"
|
return "on MangoWC";
|
||||||
return ""
|
if (CompositorService.isSway)
|
||||||
|
return "on Sway";
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
|
||||||
@@ -82,27 +88,10 @@ Card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: uptimeText
|
text: DgopService.shortUptime || "up"
|
||||||
|
|
||||||
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"
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
elide: Text.ElideRight
|
|
||||||
width: availableWidth
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WeatherService.addRef();
|
WeatherService.addRef();
|
||||||
UserInfoService.refreshUserInfo();
|
UserInfoService.getUserInfo();
|
||||||
|
|
||||||
if (CompositorService.isHyprland) {
|
if (CompositorService.isHyprland) {
|
||||||
updateHyprlandLayout();
|
updateHyprlandLayout();
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
@@ -69,7 +68,7 @@ DankFlickable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: `${UserInfoService.uptime} • Boot: ${DgopService.bootTime}`
|
text: `${DgopService.uptime} • Boot: ${DgopService.bootTime}`
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
font.family: SettingsData.monoFontFamily
|
font.family: SettingsData.monoFontFamily
|
||||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
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)
|
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -134,7 +131,6 @@ DankFlickable {
|
|||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -181,9 +177,7 @@ DankFlickable {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -275,7 +269,6 @@ DankFlickable {
|
|||||||
color: Theme.secondary
|
color: Theme.secondary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -365,22 +358,16 @@ DankFlickable {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
duration: Theme.shortDuration
|
duration: Theme.shortDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -418,7 +405,6 @@ DankFlickable {
|
|||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -495,7 +481,6 @@ DankFlickable {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
@@ -596,19 +581,11 @@ DankFlickable {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -72,504 +71,547 @@ Singleton {
|
|||||||
property string bootTime: ""
|
property string bootTime: ""
|
||||||
property string motherboard: ""
|
property string motherboard: ""
|
||||||
property string biosVersion: ""
|
property string biosVersion: ""
|
||||||
|
property string uptime: ""
|
||||||
|
property string shortUptime: ""
|
||||||
|
|
||||||
property int historySize: 60
|
property int historySize: 60
|
||||||
property var cpuHistory: []
|
property var cpuHistory: []
|
||||||
property var memoryHistory: []
|
property var memoryHistory: []
|
||||||
property var networkHistory: ({
|
property var networkHistory: ({
|
||||||
"rx": [],
|
"rx": [],
|
||||||
"tx": []
|
"tx": []
|
||||||
})
|
})
|
||||||
property var diskHistory: ({
|
property var diskHistory: ({
|
||||||
"read": [],
|
"read": [],
|
||||||
"write": []
|
"write": []
|
||||||
})
|
})
|
||||||
|
|
||||||
function addRef(modules = null) {
|
function addRef(modules = null) {
|
||||||
refCount++
|
refCount++;
|
||||||
let modulesChanged = false
|
let modulesChanged = false;
|
||||||
|
|
||||||
if (modules) {
|
if (modules) {
|
||||||
const modulesToAdd = Array.isArray(modules) ? modules : [modules]
|
const modulesToAdd = Array.isArray(modules) ? modules : [modules];
|
||||||
for (const module of modulesToAdd) {
|
for (const module of modulesToAdd) {
|
||||||
// Increment reference count for this module
|
// Increment reference count for this module
|
||||||
const currentCount = moduleRefCounts[module] || 0
|
const currentCount = moduleRefCounts[module] || 0;
|
||||||
moduleRefCounts[module] = currentCount + 1
|
moduleRefCounts[module] = currentCount + 1;
|
||||||
console.log("Adding ref for module:", module, "count:", moduleRefCounts[module])
|
console.log("Adding ref for module:", module, "count:", moduleRefCounts[module]);
|
||||||
|
|
||||||
// Add to enabled modules if not already there
|
// Add to enabled modules if not already there
|
||||||
if (enabledModules.indexOf(module) === -1) {
|
if (enabledModules.indexOf(module) === -1) {
|
||||||
enabledModules.push(module)
|
enabledModules.push(module);
|
||||||
modulesChanged = true
|
modulesChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modulesChanged || refCount === 1) {
|
if (modulesChanged || refCount === 1) {
|
||||||
enabledModules = enabledModules.slice() // Force property change
|
enabledModules = enabledModules.slice(); // Force property change
|
||||||
moduleRefCounts = Object.assign({}, moduleRefCounts) // Force property change
|
moduleRefCounts = Object.assign({}, moduleRefCounts); // Force property change
|
||||||
updateAllStats()
|
updateAllStats();
|
||||||
} else if (gpuPciIds.length > 0 && refCount > 0) {
|
} else if (gpuPciIds.length > 0 && refCount > 0) {
|
||||||
// If we have GPU PCI IDs and active modules, make sure to update
|
// 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
|
// This handles the case where PCI IDs were loaded after modules were added
|
||||||
updateAllStats()
|
updateAllStats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeRef(modules = null) {
|
function removeRef(modules = null) {
|
||||||
refCount = Math.max(0, refCount - 1)
|
refCount = Math.max(0, refCount - 1);
|
||||||
let modulesChanged = false
|
let modulesChanged = false;
|
||||||
|
|
||||||
if (modules) {
|
if (modules) {
|
||||||
const modulesToRemove = Array.isArray(modules) ? modules : [modules]
|
const modulesToRemove = Array.isArray(modules) ? modules : [modules];
|
||||||
for (const module of modulesToRemove) {
|
for (const module of modulesToRemove) {
|
||||||
const currentCount = moduleRefCounts[module] || 0
|
const currentCount = moduleRefCounts[module] || 0;
|
||||||
if (currentCount > 1) {
|
if (currentCount > 1) {
|
||||||
// Decrement reference count
|
// Decrement reference count
|
||||||
moduleRefCounts[module] = currentCount - 1
|
moduleRefCounts[module] = currentCount - 1;
|
||||||
console.log("Removing ref for module:", module, "count:", moduleRefCounts[module])
|
console.log("Removing ref for module:", module, "count:", moduleRefCounts[module]);
|
||||||
} else if (currentCount === 1) {
|
} else if (currentCount === 1) {
|
||||||
// Remove completely when count reaches 0
|
// Remove completely when count reaches 0
|
||||||
delete moduleRefCounts[module]
|
delete moduleRefCounts[module];
|
||||||
const index = enabledModules.indexOf(module)
|
const index = enabledModules.indexOf(module);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
enabledModules.splice(index, 1)
|
enabledModules.splice(index, 1);
|
||||||
modulesChanged = true
|
modulesChanged = true;
|
||||||
console.log("Disabling module:", module, "(no more refs)")
|
console.log("Disabling module:", module, "(no more refs)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modulesChanged) {
|
if (modulesChanged) {
|
||||||
enabledModules = enabledModules.slice() // Force property change
|
enabledModules = enabledModules.slice(); // Force property change
|
||||||
moduleRefCounts = Object.assign({}, moduleRefCounts) // Force property change
|
moduleRefCounts = Object.assign({}, moduleRefCounts); // Force property change
|
||||||
|
|
||||||
// Clear cursor data when CPU or process modules are no longer active
|
// Clear cursor data when CPU or process modules are no longer active
|
||||||
if (!enabledModules.includes("cpu")) {
|
if (!enabledModules.includes("cpu")) {
|
||||||
cpuCursor = ""
|
cpuCursor = "";
|
||||||
cpuSampleCount = 0
|
cpuSampleCount = 0;
|
||||||
}
|
}
|
||||||
if (!enabledModules.includes("processes")) {
|
if (!enabledModules.includes("processes")) {
|
||||||
procCursor = ""
|
procCursor = "";
|
||||||
processSampleCount = 0
|
processSampleCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setGpuPciIds(pciIds) {
|
function setGpuPciIds(pciIds) {
|
||||||
gpuPciIds = Array.isArray(pciIds) ? pciIds : []
|
gpuPciIds = Array.isArray(pciIds) ? pciIds : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function addGpuPciId(pciId) {
|
function addGpuPciId(pciId) {
|
||||||
const currentCount = gpuPciIdRefCounts[pciId] || 0
|
const currentCount = gpuPciIdRefCounts[pciId] || 0;
|
||||||
gpuPciIdRefCounts[pciId] = currentCount + 1
|
gpuPciIdRefCounts[pciId] = currentCount + 1;
|
||||||
|
|
||||||
// Add to gpuPciIds array if not already there
|
// Add to gpuPciIds array if not already there
|
||||||
if (!gpuPciIds.includes(pciId)) {
|
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
|
// Force property change notification
|
||||||
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts)
|
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeGpuPciId(pciId) {
|
function removeGpuPciId(pciId) {
|
||||||
const currentCount = gpuPciIdRefCounts[pciId] || 0
|
const currentCount = gpuPciIdRefCounts[pciId] || 0;
|
||||||
if (currentCount > 1) {
|
if (currentCount > 1) {
|
||||||
// Decrement reference count
|
// Decrement reference count
|
||||||
gpuPciIdRefCounts[pciId] = currentCount - 1
|
gpuPciIdRefCounts[pciId] = currentCount - 1;
|
||||||
console.log("Removing GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId])
|
console.log("Removing GPU PCI ID ref:", pciId, "count:", gpuPciIdRefCounts[pciId]);
|
||||||
} else if (currentCount === 1) {
|
} else if (currentCount === 1) {
|
||||||
// Remove completely when count reaches 0
|
// Remove completely when count reaches 0
|
||||||
delete gpuPciIdRefCounts[pciId]
|
delete gpuPciIdRefCounts[pciId];
|
||||||
const index = gpuPciIds.indexOf(pciId)
|
const index = gpuPciIds.indexOf(pciId);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
gpuPciIds = gpuPciIds.slice()
|
gpuPciIds = gpuPciIds.slice();
|
||||||
gpuPciIds.splice(index, 1)
|
gpuPciIds.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear temperature data for this GPU when no longer monitored
|
// Clear temperature data for this GPU when no longer monitored
|
||||||
if (availableGpus && availableGpus.length > 0) {
|
if (availableGpus && availableGpus.length > 0) {
|
||||||
const updatedGpus = availableGpus.slice()
|
const updatedGpus = availableGpus.slice();
|
||||||
for (var i = 0; i < updatedGpus.length; i++) {
|
for (var i = 0; i < updatedGpus.length; i++) {
|
||||||
if (updatedGpus[i].pciId === pciId) {
|
if (updatedGpus[i].pciId === pciId) {
|
||||||
updatedGpus[i] = Object.assign({}, updatedGpus[i], {
|
updatedGpus[i] = Object.assign({}, updatedGpus[i], {
|
||||||
"temperature": 0
|
"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
|
// Force property change notification
|
||||||
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts)
|
gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setProcessOptions(limit = 20, sort = "cpu", disableCpu = false) {
|
function setProcessOptions(limit = 20, sort = "cpu", disableCpu = false) {
|
||||||
processLimit = limit
|
processLimit = limit;
|
||||||
processSort = sort
|
processSort = sort;
|
||||||
noCpu = disableCpu
|
noCpu = disableCpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAllStats() {
|
function updateAllStats() {
|
||||||
if (dgopAvailable && refCount > 0 && enabledModules.length > 0) {
|
if (dgopAvailable && refCount > 0 && enabledModules.length > 0) {
|
||||||
isUpdating = true
|
isUpdating = true;
|
||||||
dgopProcess.running = true
|
dgopProcess.running = true;
|
||||||
} else {
|
} else {
|
||||||
isUpdating = false
|
isUpdating = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeGpuMetadata() {
|
function initializeGpuMetadata() {
|
||||||
if (!dgopAvailable)
|
if (!dgopAvailable)
|
||||||
return
|
return;
|
||||||
gpuInitProcess.running = true
|
gpuInitProcess.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeSystemMetadata() {
|
function initializeSystemMetadata() {
|
||||||
if (!dgopAvailable)
|
if (!dgopAvailable)
|
||||||
return
|
return;
|
||||||
systemInitProcess.running = true
|
systemInitProcess.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDgopCommand() {
|
function buildDgopCommand() {
|
||||||
const cmd = ["dgop", "meta", "--json"]
|
const cmd = ["dgop", "meta", "--json"];
|
||||||
|
|
||||||
if (enabledModules.length === 0) {
|
if (enabledModules.length === 0) {
|
||||||
// Don't run if no modules are needed
|
// Don't run if no modules are needed
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace 'gpu' with 'gpu-temp' when we have PCI IDs to monitor
|
// Replace 'gpu' with 'gpu-temp' when we have PCI IDs to monitor
|
||||||
const finalModules = []
|
const finalModules = [];
|
||||||
for (const module of enabledModules) {
|
for (const module of enabledModules) {
|
||||||
if (module === "gpu" && gpuPciIds.length > 0) {
|
if (module === "gpu" && gpuPciIds.length > 0) {
|
||||||
finalModules.push("gpu-temp")
|
finalModules.push("gpu-temp");
|
||||||
} else if (module !== "gpu") {
|
} else if (module !== "gpu") {
|
||||||
finalModules.push(module)
|
finalModules.push(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add gpu-temp module automatically when we have PCI IDs to monitor
|
// Add gpu-temp module automatically when we have PCI IDs to monitor
|
||||||
if (gpuPciIds.length > 0 && finalModules.indexOf("gpu-temp") === -1) {
|
if (gpuPciIds.length > 0 && finalModules.indexOf("gpu-temp") === -1) {
|
||||||
finalModules.push("gpu-temp")
|
finalModules.push("gpu-temp");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabledModules.indexOf("all") !== -1) {
|
if (enabledModules.indexOf("all") !== -1) {
|
||||||
cmd.push("--modules", "all")
|
cmd.push("--modules", "all");
|
||||||
} else if (finalModules.length > 0) {
|
} else if (finalModules.length > 0) {
|
||||||
const moduleList = finalModules.join(",")
|
const moduleList = finalModules.join(",");
|
||||||
cmd.push("--modules", moduleList)
|
cmd.push("--modules", moduleList);
|
||||||
} else {
|
} else {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add cursor data if available for accurate CPU percentages
|
// Add cursor data if available for accurate CPU percentages
|
||||||
if ((enabledModules.includes("cpu") || enabledModules.includes("all")) && cpuCursor) {
|
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) {
|
if ((enabledModules.includes("processes") || enabledModules.includes("all")) && procCursor) {
|
||||||
cmd.push("--proc-cursor", procCursor)
|
cmd.push("--proc-cursor", procCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpuPciIds.length > 0) {
|
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) {
|
if (enabledModules.indexOf("processes") !== -1 || enabledModules.indexOf("all") !== -1) {
|
||||||
cmd.push("--limit", "100") // Get more data for client sorting
|
cmd.push("--limit", "100"); // Get more data for client sorting
|
||||||
cmd.push("--sort", "cpu") // Always get CPU sorted data
|
cmd.push("--sort", "cpu"); // Always get CPU sorted data
|
||||||
if (noCpu) {
|
if (noCpu) {
|
||||||
cmd.push("--no-cpu")
|
cmd.push("--no-cpu");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseData(data) {
|
function parseData(data) {
|
||||||
if (data.cpu) {
|
if (data.cpu) {
|
||||||
const cpu = data.cpu
|
const cpu = data.cpu;
|
||||||
cpuSampleCount++
|
cpuSampleCount++;
|
||||||
|
|
||||||
cpuUsage = cpu.usage || 0
|
cpuUsage = cpu.usage || 0;
|
||||||
cpuFrequency = cpu.frequency || 0
|
cpuFrequency = cpu.frequency || 0;
|
||||||
cpuTemperature = cpu.temperature || 0
|
cpuTemperature = cpu.temperature || 0;
|
||||||
cpuCores = cpu.count || 1
|
cpuCores = cpu.count || 1;
|
||||||
cpuModel = cpu.model || ""
|
cpuModel = cpu.model || "";
|
||||||
perCoreCpuUsage = cpu.coreUsage || []
|
perCoreCpuUsage = cpu.coreUsage || [];
|
||||||
addToHistory(cpuHistory, cpuUsage)
|
addToHistory(cpuHistory, cpuUsage);
|
||||||
|
|
||||||
if (cpu.cursor) {
|
if (cpu.cursor) {
|
||||||
cpuCursor = cpu.cursor
|
cpuCursor = cpu.cursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.memory) {
|
if (data.memory) {
|
||||||
const mem = data.memory
|
const mem = data.memory;
|
||||||
const totalKB = mem.total || 0
|
const totalKB = mem.total || 0;
|
||||||
const availableKB = mem.available || 0
|
const availableKB = mem.available || 0;
|
||||||
const freeKB = mem.free || 0
|
const freeKB = mem.free || 0;
|
||||||
|
|
||||||
totalMemoryMB = totalKB / 1024
|
totalMemoryMB = totalKB / 1024;
|
||||||
availableMemoryMB = availableKB / 1024
|
availableMemoryMB = availableKB / 1024;
|
||||||
freeMemoryMB = freeKB / 1024
|
freeMemoryMB = freeKB / 1024;
|
||||||
usedMemoryMB = totalMemoryMB - availableMemoryMB
|
usedMemoryMB = totalMemoryMB - availableMemoryMB;
|
||||||
memoryUsage = totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0
|
memoryUsage = totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0;
|
||||||
|
|
||||||
totalMemoryKB = totalKB
|
totalMemoryKB = totalKB;
|
||||||
usedMemoryKB = totalKB - availableKB
|
usedMemoryKB = totalKB - availableKB;
|
||||||
totalSwapKB = mem.swaptotal || 0
|
totalSwapKB = mem.swaptotal || 0;
|
||||||
usedSwapKB = (mem.swaptotal || 0) - (mem.swapfree || 0)
|
usedSwapKB = (mem.swaptotal || 0) - (mem.swapfree || 0);
|
||||||
|
|
||||||
addToHistory(memoryHistory, memoryUsage)
|
addToHistory(memoryHistory, memoryUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.network && Array.isArray(data.network)) {
|
if (data.network && Array.isArray(data.network)) {
|
||||||
networkInterfaces = data.network
|
networkInterfaces = data.network;
|
||||||
|
|
||||||
let totalRx = 0
|
let totalRx = 0;
|
||||||
let totalTx = 0
|
let totalTx = 0;
|
||||||
for (const iface of data.network) {
|
for (const iface of data.network) {
|
||||||
totalRx += iface.rx || 0
|
totalRx += iface.rx || 0;
|
||||||
totalTx += iface.tx || 0
|
totalTx += iface.tx || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastNetworkStats) {
|
if (lastNetworkStats) {
|
||||||
const timeDiff = updateInterval / 1000
|
const timeDiff = updateInterval / 1000;
|
||||||
const rxDiff = totalRx - lastNetworkStats.rx
|
const rxDiff = totalRx - lastNetworkStats.rx;
|
||||||
const txDiff = totalTx - lastNetworkStats.tx
|
const txDiff = totalTx - lastNetworkStats.tx;
|
||||||
networkRxRate = Math.max(0, rxDiff / timeDiff)
|
networkRxRate = Math.max(0, rxDiff / timeDiff);
|
||||||
networkTxRate = Math.max(0, txDiff / timeDiff)
|
networkTxRate = Math.max(0, txDiff / timeDiff);
|
||||||
addToHistory(networkHistory.rx, networkRxRate / 1024)
|
addToHistory(networkHistory.rx, networkRxRate / 1024);
|
||||||
addToHistory(networkHistory.tx, networkTxRate / 1024)
|
addToHistory(networkHistory.tx, networkTxRate / 1024);
|
||||||
}
|
}
|
||||||
lastNetworkStats = {
|
lastNetworkStats = {
|
||||||
"rx": totalRx,
|
"rx": totalRx,
|
||||||
"tx": totalTx
|
"tx": totalTx
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.disk && Array.isArray(data.disk)) {
|
if (data.disk && Array.isArray(data.disk)) {
|
||||||
diskDevices = data.disk
|
diskDevices = data.disk;
|
||||||
|
|
||||||
let totalRead = 0
|
let totalRead = 0;
|
||||||
let totalWrite = 0
|
let totalWrite = 0;
|
||||||
for (const disk of data.disk) {
|
for (const disk of data.disk) {
|
||||||
totalRead += (disk.read || 0) * 512
|
totalRead += (disk.read || 0) * 512;
|
||||||
totalWrite += (disk.write || 0) * 512
|
totalWrite += (disk.write || 0) * 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastDiskStats) {
|
if (lastDiskStats) {
|
||||||
const timeDiff = updateInterval / 1000
|
const timeDiff = updateInterval / 1000;
|
||||||
const readDiff = totalRead - lastDiskStats.read
|
const readDiff = totalRead - lastDiskStats.read;
|
||||||
const writeDiff = totalWrite - lastDiskStats.write
|
const writeDiff = totalWrite - lastDiskStats.write;
|
||||||
diskReadRate = Math.max(0, readDiff / timeDiff)
|
diskReadRate = Math.max(0, readDiff / timeDiff);
|
||||||
diskWriteRate = Math.max(0, writeDiff / timeDiff)
|
diskWriteRate = Math.max(0, writeDiff / timeDiff);
|
||||||
addToHistory(diskHistory.read, diskReadRate / (1024 * 1024))
|
addToHistory(diskHistory.read, diskReadRate / (1024 * 1024));
|
||||||
addToHistory(diskHistory.write, diskWriteRate / (1024 * 1024))
|
addToHistory(diskHistory.write, diskWriteRate / (1024 * 1024));
|
||||||
}
|
}
|
||||||
lastDiskStats = {
|
lastDiskStats = {
|
||||||
"read": totalRead,
|
"read": totalRead,
|
||||||
"write": totalWrite
|
"write": totalWrite
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.diskmounts) {
|
if (data.diskmounts) {
|
||||||
diskMounts = data.diskmounts || []
|
diskMounts = data.diskmounts || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.processes && Array.isArray(data.processes)) {
|
if (data.processes && Array.isArray(data.processes)) {
|
||||||
const newProcesses = []
|
const newProcesses = [];
|
||||||
processSampleCount++
|
processSampleCount++;
|
||||||
|
|
||||||
for (const proc of data.processes) {
|
for (const proc of data.processes) {
|
||||||
const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0
|
const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0;
|
||||||
|
|
||||||
newProcesses.push({
|
newProcesses.push({
|
||||||
"pid": proc.pid || 0,
|
"pid": proc.pid || 0,
|
||||||
"ppid": proc.ppid || 0,
|
"ppid": proc.ppid || 0,
|
||||||
"cpu": cpuUsage,
|
"cpu": cpuUsage,
|
||||||
"memoryPercent": proc.memoryPercent || proc.pssPercent || 0,
|
"memoryPercent": proc.memoryPercent || proc.pssPercent || 0,
|
||||||
"memoryKB": proc.memoryKB || proc.pssKB || 0,
|
"memoryKB": proc.memoryKB || proc.pssKB || 0,
|
||||||
"command": proc.command || "",
|
"command": proc.command || "",
|
||||||
"fullCommand": proc.fullCommand || "",
|
"fullCommand": proc.fullCommand || "",
|
||||||
"displayName": (proc.command && proc.command.length > 15) ? proc.command.substring(0, 15) + "..." : (proc.command || "")
|
"displayName": (proc.command && proc.command.length > 15) ? proc.command.substring(0, 15) + "..." : (proc.command || "")
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
allProcesses = newProcesses
|
allProcesses = newProcesses;
|
||||||
applySorting()
|
applySorting();
|
||||||
|
|
||||||
if (data.cursor) {
|
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)) {
|
if (gpuData && Array.isArray(gpuData)) {
|
||||||
// Check if this is temperature update data (has PCI IDs being monitored)
|
// Check if this is temperature update data (has PCI IDs being monitored)
|
||||||
if (gpuPciIds.length > 0 && availableGpus && availableGpus.length > 0) {
|
if (gpuPciIds.length > 0 && availableGpus && availableGpus.length > 0) {
|
||||||
// This is temperature data - merge with existing GPU metadata
|
// 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++) {
|
for (var i = 0; i < updatedGpus.length; i++) {
|
||||||
const existingGpu = updatedGpus[i]
|
const existingGpu = updatedGpus[i];
|
||||||
const tempGpu = gpuData.find(g => g.pciId === existingGpu.pciId)
|
const tempGpu = gpuData.find(g => g.pciId === existingGpu.pciId);
|
||||||
// Only update temperature if this GPU's PCI ID is being monitored
|
// Only update temperature if this GPU's PCI ID is being monitored
|
||||||
if (tempGpu && gpuPciIds.includes(existingGpu.pciId)) {
|
if (tempGpu && gpuPciIds.includes(existingGpu.pciId)) {
|
||||||
updatedGpus[i] = Object.assign({}, existingGpu, {
|
updatedGpus[i] = Object.assign({}, existingGpu, {
|
||||||
"temperature": tempGpu.temperature || 0
|
"temperature": tempGpu.temperature || 0
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
availableGpus = updatedGpus
|
availableGpus = updatedGpus;
|
||||||
} else {
|
} else {
|
||||||
// This is initial GPU metadata - set the full list
|
// This is initial GPU metadata - set the full list
|
||||||
const gpuList = []
|
const gpuList = [];
|
||||||
for (const gpu of gpuData) {
|
for (const gpu of gpuData) {
|
||||||
let displayName = gpu.displayName || gpu.name || "Unknown GPU"
|
let displayName = gpu.displayName || gpu.name || "Unknown GPU";
|
||||||
let fullName = gpu.fullName || gpu.name || "Unknown GPU"
|
let fullName = gpu.fullName || gpu.name || "Unknown GPU";
|
||||||
|
|
||||||
gpuList.push({
|
gpuList.push({
|
||||||
"driver": gpu.driver || "",
|
"driver": gpu.driver || "",
|
||||||
"vendor": gpu.vendor || "",
|
"vendor": gpu.vendor || "",
|
||||||
"displayName": displayName,
|
"displayName": displayName,
|
||||||
"fullName": fullName,
|
"fullName": fullName,
|
||||||
"pciId": gpu.pciId || "",
|
"pciId": gpu.pciId || "",
|
||||||
"temperature": gpu.temperature || 0
|
"temperature": gpu.temperature || 0
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
availableGpus = gpuList
|
availableGpus = gpuList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.system) {
|
if (data.system) {
|
||||||
const sys = data.system
|
const sys = data.system;
|
||||||
loadAverage = sys.loadavg || ""
|
loadAverage = sys.loadavg || "";
|
||||||
processCount = sys.processes || 0
|
processCount = sys.processes || 0;
|
||||||
threadCount = sys.threads || 0
|
threadCount = sys.threads || 0;
|
||||||
bootTime = sys.boottime || ""
|
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) {
|
if (hwData) {
|
||||||
hostname = hwData.hostname || ""
|
hostname = hwData.hostname || "";
|
||||||
kernelVersion = hwData.kernel || ""
|
kernelVersion = hwData.kernel || "";
|
||||||
distribution = hwData.distro || ""
|
distribution = hwData.distro || "";
|
||||||
architecture = hwData.arch || ""
|
architecture = hwData.arch || "";
|
||||||
motherboard = (hwData.bios && hwData.bios.motherboard) || ""
|
motherboard = (hwData.bios && hwData.bios.motherboard) || "";
|
||||||
biosVersion = (hwData.bios && hwData.bios.version) || ""
|
biosVersion = (hwData.bios && hwData.bios.version) || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
isUpdating = false
|
isUpdating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addToHistory(array, value) {
|
function addToHistory(array, value) {
|
||||||
array.push(value)
|
array.push(value);
|
||||||
if (array.length > historySize) {
|
if (array.length > historySize) {
|
||||||
array.shift()
|
array.shift();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProcessIcon(command) {
|
function getProcessIcon(command) {
|
||||||
const cmd = command.toLowerCase()
|
const cmd = command.toLowerCase();
|
||||||
if (cmd.includes("firefox") || cmd.includes("chrome") || cmd.includes("browser") || cmd.includes("chromium")) {
|
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")) {
|
if (cmd.includes("code") || cmd.includes("editor") || cmd.includes("vim")) {
|
||||||
return "code"
|
return "code";
|
||||||
}
|
}
|
||||||
if (cmd.includes("terminal") || cmd.includes("bash") || cmd.includes("zsh")) {
|
if (cmd.includes("terminal") || cmd.includes("bash") || cmd.includes("zsh")) {
|
||||||
return "terminal"
|
return "terminal";
|
||||||
}
|
}
|
||||||
if (cmd.includes("music") || cmd.includes("audio") || cmd.includes("spotify")) {
|
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")) {
|
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")) {
|
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) {
|
function formatCpuUsage(cpu) {
|
||||||
return (cpu || 0).toFixed(1) + "%"
|
return (cpu || 0).toFixed(1) + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatMemoryUsage(memoryKB) {
|
function formatMemoryUsage(memoryKB) {
|
||||||
const mem = memoryKB || 0
|
const mem = memoryKB || 0;
|
||||||
if (mem < 1024) {
|
if (mem < 1024) {
|
||||||
return mem.toFixed(0) + " KB"
|
return mem.toFixed(0) + " KB";
|
||||||
} else if (mem < 1024 * 1024) {
|
} else if (mem < 1024 * 1024) {
|
||||||
return (mem / 1024).toFixed(1) + " MB"
|
return (mem / 1024).toFixed(1) + " MB";
|
||||||
} else {
|
} else {
|
||||||
return (mem / (1024 * 1024)).toFixed(1) + " GB"
|
return (mem / (1024 * 1024)).toFixed(1) + " GB";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatSystemMemory(memoryKB) {
|
function formatSystemMemory(memoryKB) {
|
||||||
const mem = memoryKB || 0
|
const mem = memoryKB || 0;
|
||||||
if (mem === 0) {
|
if (mem === 0) {
|
||||||
return "--"
|
return "--";
|
||||||
}
|
}
|
||||||
if (mem < 1024 * 1024) {
|
if (mem < 1024 * 1024) {
|
||||||
return (mem / 1024).toFixed(0) + " MB"
|
return (mem / 1024).toFixed(0) + " MB";
|
||||||
} else {
|
} else {
|
||||||
return (mem / (1024 * 1024)).toFixed(1) + " GB"
|
return (mem / (1024 * 1024)).toFixed(1) + " GB";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function killProcess(pid) {
|
function killProcess(pid) {
|
||||||
if (pid > 0) {
|
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) {
|
function setSortBy(newSortBy) {
|
||||||
if (newSortBy !== currentSort) {
|
if (newSortBy !== currentSort) {
|
||||||
currentSort = newSortBy
|
currentSort = newSortBy;
|
||||||
applySorting()
|
applySorting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applySorting() {
|
function applySorting() {
|
||||||
if (!allProcesses || allProcesses.length === 0) {
|
if (!allProcesses || allProcesses.length === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sorted = allProcesses.slice()
|
const sorted = allProcesses.slice();
|
||||||
sorted.sort((a, b) => {
|
sorted.sort((a, b) => {
|
||||||
let valueA, valueB
|
let valueA, valueB;
|
||||||
|
|
||||||
switch (currentSort) {
|
switch (currentSort) {
|
||||||
case "cpu":
|
case "cpu":
|
||||||
valueA = a.cpu || 0
|
valueA = a.cpu || 0;
|
||||||
valueB = b.cpu || 0
|
valueB = b.cpu || 0;
|
||||||
return valueB - valueA
|
return valueB - valueA;
|
||||||
case "memory":
|
case "memory":
|
||||||
valueA = a.memoryKB || 0
|
valueA = a.memoryKB || 0;
|
||||||
valueB = b.memoryKB || 0
|
valueB = b.memoryKB || 0;
|
||||||
return valueB - valueA
|
return valueB - valueA;
|
||||||
case "name":
|
case "name":
|
||||||
valueA = (a.command || "").toLowerCase()
|
valueA = (a.command || "").toLowerCase();
|
||||||
valueB = (b.command || "").toLowerCase()
|
valueB = (b.command || "").toLowerCase();
|
||||||
return valueA.localeCompare(valueB)
|
return valueA.localeCompare(valueB);
|
||||||
case "pid":
|
case "pid":
|
||||||
valueA = a.pid || 0
|
valueA = a.pid || 0;
|
||||||
valueB = b.pid || 0
|
valueB = b.pid || 0;
|
||||||
return valueA - valueB
|
return valueA - valueB;
|
||||||
default:
|
default:
|
||||||
return 0
|
return 0;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
processes = sorted.slice(0, processLimit)
|
processes = sorted.slice(0, processLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -585,26 +627,26 @@ Singleton {
|
|||||||
id: dgopProcess
|
id: dgopProcess
|
||||||
command: root.buildDgopCommand()
|
command: root.buildDgopCommand()
|
||||||
running: false
|
running: false
|
||||||
onCommandChanged: {
|
onCommandChanged:
|
||||||
|
|
||||||
//console.log("DgopService command:", JSON.stringify(command))
|
//console.log("DgopService command:", JSON.stringify(command))
|
||||||
}
|
{}
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
console.warn("Dgop process failed with exit code:", exitCode)
|
console.warn("Dgop process failed with exit code:", exitCode);
|
||||||
isUpdating = false
|
isUpdating = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(text.trim())
|
const data = JSON.parse(text.trim());
|
||||||
parseData(data)
|
parseData(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Failed to parse dgop JSON:", e)
|
console.warn("Failed to parse dgop JSON:", e);
|
||||||
console.warn("Raw text was:", text.substring(0, 200))
|
console.warn("Raw text was:", text.substring(0, 200));
|
||||||
isUpdating = false
|
isUpdating = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -617,17 +659,17 @@ Singleton {
|
|||||||
running: false
|
running: false
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode !== 0) {
|
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 {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(text.trim())
|
const data = JSON.parse(text.trim());
|
||||||
parseData(data)
|
parseData(data);
|
||||||
} catch (e) {
|
} 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
|
running: false
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode !== 0) {
|
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 {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(text.trim())
|
const data = JSON.parse(text.trim());
|
||||||
parseData(data)
|
parseData(data);
|
||||||
} catch (e) {
|
} 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"]
|
command: ["which", "dgop"]
|
||||||
running: false
|
running: false
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
dgopAvailable = (exitCode === 0)
|
dgopAvailable = (exitCode === 0);
|
||||||
if (dgopAvailable) {
|
if (dgopAvailable) {
|
||||||
initializeGpuMetadata()
|
initializeGpuMetadata();
|
||||||
initializeSystemMetadata()
|
initializeSystemMetadata();
|
||||||
if (SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.length > 0) {
|
if (SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.length > 0) {
|
||||||
for (const pciId of SessionData.enabledGpuPciIds) {
|
for (const pciId of SessionData.enabledGpuPciIds) {
|
||||||
addGpuPciId(pciId)
|
addGpuPciId(pciId);
|
||||||
}
|
}
|
||||||
if (refCount > 0 && enabledModules.length > 0) {
|
if (refCount > 0 && enabledModules.length > 0) {
|
||||||
updateAllStats()
|
updateAllStats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
running: false
|
||||||
onExited: exitCode => {
|
onExited: exitCode => {
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
console.warn("Failed to read /etc/os-release")
|
console.warn("Failed to read /etc/os-release");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
onStreamFinished: {
|
onStreamFinished: {
|
||||||
if (text.trim()) {
|
if (text.trim()) {
|
||||||
try {
|
try {
|
||||||
const lines = text.trim().split('\n')
|
const lines = text.trim().split('\n');
|
||||||
let prettyName = ""
|
let prettyName = "";
|
||||||
let name = ""
|
let name = "";
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const trimmedLine = line.trim()
|
const trimmedLine = line.trim();
|
||||||
if (trimmedLine.startsWith('PRETTY_NAME=')) {
|
if (trimmedLine.startsWith('PRETTY_NAME=')) {
|
||||||
prettyName = trimmedLine.substring(12).replace(/^["']|["']$/g, '')
|
prettyName = trimmedLine.substring(12).replace(/^["']|["']$/g, '');
|
||||||
} else if (trimmedLine.startsWith('NAME=')) {
|
} else if (trimmedLine.startsWith('NAME=')) {
|
||||||
name = trimmedLine.substring(5).replace(/^["']|["']$/g, '')
|
name = trimmedLine.substring(5).replace(/^["']|["']$/g, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefer PRETTY_NAME, fallback to NAME
|
// Prefer PRETTY_NAME, fallback to NAME
|
||||||
const distroName = prettyName || name || "Linux"
|
const distroName = prettyName || name || "Linux";
|
||||||
distribution = distroName
|
distribution = distroName;
|
||||||
console.info("Detected distribution:", distroName)
|
console.info("Detected distribution:", distroName);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Failed to parse /etc/os-release:", e)
|
console.warn("Failed to parse /etc/os-release:", e);
|
||||||
distribution = "Linux"
|
distribution = "Linux";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -720,7 +762,7 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
dgopCheckProcess.running = true
|
dgopCheckProcess.running = true;
|
||||||
osReleaseProcess.running = true
|
osReleaseProcess.running = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -12,77 +11,25 @@ Singleton {
|
|||||||
property string username: ""
|
property string username: ""
|
||||||
property string fullName: ""
|
property string fullName: ""
|
||||||
property string profilePicture: ""
|
property string profilePicture: ""
|
||||||
property string uptime: ""
|
|
||||||
property string shortUptime: ""
|
|
||||||
property string hostname: ""
|
property string hostname: ""
|
||||||
property bool profileAvailable: false
|
property bool profileAvailable: false
|
||||||
|
|
||||||
function getUserInfo() {
|
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) {
|
if (exitCode !== 0) {
|
||||||
root.username = "User"
|
root.username = "User";
|
||||||
root.fullName = "User"
|
root.fullName = "User";
|
||||||
root.hostname = "System"
|
root.hostname = "System";
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
const parts = output.trim().split("|")
|
const parts = output.trim().split("|");
|
||||||
if (parts.length >= 3) {
|
if (parts.length >= 3) {
|
||||||
root.username = parts[0] || ""
|
root.username = parts[0] || "";
|
||||||
root.fullName = parts[1] || parts[0] || ""
|
root.fullName = parts[1] || parts[0] || "";
|
||||||
root.hostname = parts[2] || ""
|
root.hostname = parts[2] || "";
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUptime() {
|
Component.onCompleted: getUserInfo()
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user