diff options
| author | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
|---|---|---|
| committer | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
| commit | 70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch) | |
| tree | ab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/DgopService.qml | |
| parent | 5d94c0a7d44a2255b81815a52a7056a94a39842d (diff) | |
| download | RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip | |
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/DgopService.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/DgopService.qml | 778 |
1 files changed, 778 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/DgopService.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/DgopService.qml new file mode 100644 index 0000000..e63c5c5 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/DgopService.qml @@ -0,0 +1,778 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Common + +Singleton { + id: root + + property int refCount: 0 + property int updateInterval: refCount > 0 ? 3000 : 30000 + property bool isUpdating: false + property bool dgopAvailable: false + + property var moduleRefCounts: ({}) + property var enabledModules: [] + property var gpuPciIds: [] + property var gpuPciIdRefCounts: ({}) + property int processLimit: 20 + property string processSort: "cpu" + property bool noCpu: false + property int dgopProcessPid: 0 + + // Cursor data for accurate CPU calculations + property string cpuCursor: "" + property string procCursor: "" + property int cpuSampleCount: 0 + property int processSampleCount: 0 + + property real cpuUsage: 0 + property real cpuFrequency: 0 + property real cpuTemperature: 0 + property int cpuCores: 1 + property string cpuModel: "" + property var perCoreCpuUsage: [] + + property real memoryUsage: 0 + property real totalMemoryMB: 0 + property real usedMemoryMB: 0 + property real freeMemoryMB: 0 + property real availableMemoryMB: 0 + property int totalMemoryKB: 0 + property int usedMemoryKB: 0 + property int totalSwapKB: 0 + property int usedSwapKB: 0 + + property real networkRxRate: 0 + property real networkTxRate: 0 + property var lastNetworkStats: null + property var networkInterfaces: [] + + property real diskReadRate: 0 + property real diskWriteRate: 0 + property var lastDiskStats: null + property var diskMounts: [] + property var diskDevices: [] + + property var processes: [] + property var allProcesses: [] + property string currentSort: "cpu" + property bool sortAscending: false + property var availableGpus: [] + + property string kernelVersion: "" + property string distribution: "" + property string hostname: "" + property string architecture: "" + property string loadAverage: "" + property int processCount: 0 + property int threadCount: 0 + property string bootTime: "" + property string motherboard: "" + property string biosVersion: "" + property string uptime: "" + property string shortUptime: "" + + property int historySize: 60 + property var cpuHistory: [] + property var memoryHistory: [] + property var networkHistory: ({ + "rx": [], + "tx": [] + }) + property var diskHistory: ({ + "read": [], + "write": [] + }) + + function addRef(modules = null) { + refCount++; + let modulesChanged = false; + + if (modules) { + const modulesToAdd = Array.isArray(modules) ? modules : [modules]; + for (const module of modulesToAdd) { + const currentCount = moduleRefCounts[module] || 0; + moduleRefCounts[module] = currentCount + 1; + + // Add to enabled modules if not already there + if (enabledModules.indexOf(module) === -1) { + enabledModules.push(module); + modulesChanged = true; + } + } + } + + if (modulesChanged || refCount === 1) { + 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(); + } + } + + function removeRef(modules = null) { + refCount = Math.max(0, refCount - 1); + let modulesChanged = false; + + if (modules) { + const modulesToRemove = Array.isArray(modules) ? modules : [modules]; + for (const module of modulesToRemove) { + const currentCount = moduleRefCounts[module] || 0; + if (currentCount > 1) { + moduleRefCounts[module] = currentCount - 1; + } else if (currentCount === 1) { + delete moduleRefCounts[module]; + const index = enabledModules.indexOf(module); + if (index > -1) { + enabledModules.splice(index, 1); + modulesChanged = true; + } + } + } + } + + if (modulesChanged) { + 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; + } + if (!enabledModules.includes("processes")) { + procCursor = ""; + processSampleCount = 0; + } + } + } + + function setGpuPciIds(pciIds) { + gpuPciIds = Array.isArray(pciIds) ? pciIds : []; + } + + function addGpuPciId(pciId) { + 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]); + } + + gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts); + } + + function removeGpuPciId(pciId) { + const currentCount = gpuPciIdRefCounts[pciId] || 0; + if (currentCount > 1) { + gpuPciIdRefCounts[pciId] = currentCount - 1; + } else if (currentCount === 1) { + // Remove completely when count reaches 0 + delete gpuPciIdRefCounts[pciId]; + const index = gpuPciIds.indexOf(pciId); + if (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(); + for (var i = 0; i < updatedGpus.length; i++) { + if (updatedGpus[i].pciId === pciId) { + updatedGpus[i] = Object.assign({}, updatedGpus[i], { + "temperature": 0 + }); + } + } + availableGpus = updatedGpus; + } + } + + // Force property change notification + gpuPciIdRefCounts = Object.assign({}, gpuPciIdRefCounts); + } + + function setProcessOptions(limit = 20, sort = "cpu", disableCpu = false) { + processLimit = limit; + processSort = sort; + noCpu = disableCpu; + } + + function updateAllStats() { + if (dgopAvailable && refCount > 0 && enabledModules.length > 0) { + isUpdating = true; + dgopProcess.running = true; + } else { + isUpdating = false; + } + } + + function initializeGpuMetadata() { + if (!dgopAvailable) + return; + gpuInitProcess.running = true; + } + + function initializeSystemMetadata() { + if (!dgopAvailable) + return; + systemInitProcess.running = true; + } + + function buildDgopCommand() { + const cmd = ["dgop", "meta", "--json"]; + + if (enabledModules.length === 0) { + // Don't run if no modules are needed + return []; + } + + // Replace 'gpu' with 'gpu-temp' when we have PCI IDs to monitor + const finalModules = []; + for (const module of enabledModules) { + if (module === "gpu" && gpuPciIds.length > 0) { + finalModules.push("gpu-temp"); + } else if (module !== "gpu") { + 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"); + } + + if (enabledModules.indexOf("all") !== -1) { + cmd.push("--modules", "all"); + } else if (finalModules.length > 0) { + const moduleList = finalModules.join(","); + cmd.push("--modules", moduleList); + } else { + return []; + } + + // Add cursor data if available for accurate CPU percentages + if ((enabledModules.includes("cpu") || enabledModules.includes("all")) && cpuCursor) { + cmd.push("--cpu-cursor", cpuCursor); + } + if ((enabledModules.includes("processes") || enabledModules.includes("all")) && procCursor) { + cmd.push("--proc-cursor", procCursor); + } + + if (gpuPciIds.length > 0) { + 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 + if (noCpu) { + cmd.push("--no-cpu"); + } + } + + return cmd; + } + + function parseData(data) { + if (data.cpu) { + const cpu = data.cpu; + cpuSampleCount++; + + cpuUsage = Math.round((cpu.usage || 0) * 10) / 10; + cpuFrequency = Math.round(cpu.frequency || 0); + cpuTemperature = Math.round(cpu.temperature || 0); + cpuCores = cpu.count || 1; + cpuModel = cpu.model || ""; + perCoreCpuUsage = cpu.coreUsage || []; + addToHistory(cpuHistory, cpuUsage); + + if (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 usedKB = mem.used !== undefined ? mem.used : (totalKB - availableKB); + + totalMemoryMB = Math.round(totalKB / 1024); + availableMemoryMB = Math.round(availableKB / 1024); + freeMemoryMB = Math.round(freeKB / 1024); + usedMemoryMB = Math.round(usedKB / 1024); + const rawMemUsage = mem.usedPercent !== undefined ? mem.usedPercent : (totalKB > 0 ? ((totalKB - availableKB) / totalKB) * 100 : 0); + memoryUsage = Math.round(rawMemUsage * 10) / 10; + + totalMemoryKB = totalKB; + usedMemoryKB = usedKB; + totalSwapKB = mem.swaptotal || 0; + usedSwapKB = (mem.swaptotal || 0) - (mem.swapfree || 0); + + addToHistory(memoryHistory, memoryUsage); + } + + if (data.network && Array.isArray(data.network)) { + networkInterfaces = data.network; + + let totalRx = 0; + let totalTx = 0; + for (const iface of data.network) { + 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); + } + lastNetworkStats = { + "rx": totalRx, + "tx": totalTx + }; + } + + if (data.disk && Array.isArray(data.disk)) { + diskDevices = data.disk; + + let totalRead = 0; + let totalWrite = 0; + for (const disk of data.disk) { + 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)); + } + lastDiskStats = { + "read": totalRead, + "write": totalWrite + }; + } + + if (data.diskmounts) { + diskMounts = data.diskmounts || []; + } + + if (data.processes && Array.isArray(data.processes)) { + const newProcesses = []; + processSampleCount++; + const ourPid = dgopProcessPid; + + for (const proc of data.processes) { + if (ourPid > 0 && proc.pid === ourPid) + continue; + + const cpuUsage = processSampleCount >= 2 ? (proc.cpu || 0) : 0; + + newProcesses.push({ + "pid": proc.pid || 0, + "ppid": proc.ppid || 0, + "cpu": cpuUsage, + "memoryPercent": proc.memoryPercent || proc.pssPercent || 0, + "memoryKB": proc.memoryKB || proc.pssKB || 0, + "command": proc.command || "", + "fullCommand": proc.fullCommand || "", + "username": proc.username || "", + "displayName": (proc.command && proc.command.length > 15) ? proc.command.substring(0, 15) + "..." : (proc.command || "") + }); + } + allProcesses = newProcesses; + applySorting(); + + if (data.cursor) { + procCursor = data.cursor; + } + } + + 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(); + for (var i = 0; i < updatedGpus.length; i++) { + 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; + } else { + // This is initial GPU metadata - set the full list + const gpuList = []; + for (const gpu of gpuData) { + let displayName = gpu.displayName || gpu.name || "Unknown GPU"; + let fullName = gpu.fullName || gpu.name || "Unknown GPU"; + + gpuList.push({ + "driver": gpu.driver || "", + "vendor": gpu.vendor || "", + "displayName": displayName, + "fullName": fullName, + "pciId": gpu.pciId || "", + "temperature": gpu.temperature || 0 + }); + } + availableGpus = gpuList; + } + } + + if (data.system) { + 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; + 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) || ""; + } + + isUpdating = false; + } + + function addToHistory(array, value) { + array.push(value); + if (array.length > historySize) { + array.shift(); + } + } + + function getProcessIcon(command) { + const cmd = command.toLowerCase(); + if (cmd.includes("firefox") || cmd.includes("chrome") || cmd.includes("browser") || cmd.includes("chromium")) { + return "web"; + } + if (cmd.includes("code") || cmd.includes("editor") || cmd.includes("vim")) { + return "code"; + } + if (cmd.includes("terminal") || cmd.includes("bash") || cmd.includes("zsh")) { + return "terminal"; + } + if (cmd.includes("music") || cmd.includes("audio") || cmd.includes("spotify")) { + return "music_note"; + } + if (cmd.includes("video") || cmd.includes("vlc") || cmd.includes("mpv")) { + return "play_circle"; + } + if (cmd.includes("systemd") || cmd.includes("elogind") || cmd.includes("kernel") || cmd.includes("kthread") || cmd.includes("kworker")) { + return "settings"; + } + return "memory"; + } + + function formatCpuUsage(cpu) { + return (cpu || 0).toFixed(1) + "%"; + } + + function formatMemoryUsage(memoryKB) { + const mem = memoryKB || 0; + if (mem < 1024) { + return mem.toFixed(0) + " KB"; + } else if (mem < 1024 * 1024) { + return (mem / 1024).toFixed(1) + " MB"; + } else { + return (mem / (1024 * 1024)).toFixed(1) + " GB"; + } + } + + function formatSystemMemory(memoryKB) { + const mem = memoryKB || 0; + if (mem === 0) { + return "--"; + } + if (mem < 1024 * 1024) { + return (mem / 1024).toFixed(0) + " MB"; + } else { + return (mem / (1024 * 1024)).toFixed(1) + " GB"; + } + } + + function killProcess(pid) { + if (pid > 0) { + 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; + sortAscending = false; + applySorting(); + } + } + + function toggleSort(column) { + if (column === currentSort) { + sortAscending = !sortAscending; + } else { + currentSort = column; + sortAscending = false; + } + applySorting(); + } + + function applySorting() { + if (!allProcesses || allProcesses.length === 0) + return; + + const asc = sortAscending; + const sorted = allProcesses.slice(); + sorted.sort((a, b) => { + let valueA, valueB, result; + + switch (currentSort) { + case "cpu": + valueA = a.cpu || 0; + valueB = b.cpu || 0; + result = valueB - valueA; + break; + case "memory": + valueA = a.memoryKB || 0; + valueB = b.memoryKB || 0; + result = valueB - valueA; + break; + case "name": + valueA = (a.command || "").toLowerCase(); + valueB = (b.command || "").toLowerCase(); + result = valueA.localeCompare(valueB); + break; + case "pid": + valueA = a.pid || 0; + valueB = b.pid || 0; + result = valueA - valueB; + break; + default: + return 0; + } + return asc ? -result : result; + }); + + processes = sorted.slice(0, processLimit); + } + + Timer { + id: updateTimer + interval: root.updateInterval + running: root.dgopAvailable && root.refCount > 0 && root.enabledModules.length > 0 + repeat: true + triggeredOnStart: true + onTriggered: root.updateAllStats() + } + + Process { + id: dgopProcess + command: root.buildDgopCommand() + running: false + onStarted: dgopProcessPid = processId ?? 0 + onExited: exitCode => { + if (exitCode !== 0) { + 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); + } catch (e) { + console.warn("Failed to parse dgop JSON:", e); + console.warn("Raw text was:", text.substring(0, 200)); + isUpdating = false; + } + } + } + } + } + + Process { + id: gpuInitProcess + command: ["dgop", "gpu", "--json"] + running: false + onExited: exitCode => { + if (exitCode !== 0) { + 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); + } catch (e) { + console.warn("Failed to parse GPU init JSON:", e); + } + } + } + } + } + + Process { + id: systemInitProcess + command: ["dgop", "hardware", "--json"] + running: false + onExited: exitCode => { + if (exitCode !== 0) { + 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); + } catch (e) { + console.warn("Failed to parse system init JSON:", e); + } + } + } + } + } + + Process { + id: dgopCheckProcess + command: ["which", "dgop"] + running: false + onExited: exitCode => { + dgopAvailable = (exitCode === 0); + if (dgopAvailable) { + initializeGpuMetadata(); + initializeSystemMetadata(); + if (SessionData.enabledGpuPciIds && SessionData.enabledGpuPciIds.length > 0) { + for (const pciId of SessionData.enabledGpuPciIds) { + addGpuPciId(pciId); + } + if (refCount > 0 && enabledModules.length > 0) { + updateAllStats(); + } + } + } else { + console.warn("dgop is not installed or not in PATH"); + } + } + } + + Process { + id: osReleaseProcess + command: ["cat", "/etc/os-release"] + running: false + onExited: exitCode => { + if (exitCode !== 0) { + 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 = ""; + + for (const line of lines) { + const trimmedLine = line.trim(); + if (trimmedLine.startsWith('PRETTY_NAME=')) { + prettyName = trimmedLine.substring(12).replace(/^["']|["']$/g, ''); + } else if (trimmedLine.startsWith('NAME=')) { + name = trimmedLine.substring(5).replace(/^["']|["']$/g, ''); + } + } + + // Prefer PRETTY_NAME, fallback to NAME + 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"; + } + } + } + } + } + + Component.onCompleted: { + dgopCheckProcess.running = true; + osReleaseProcess.running = true; + } +} |