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

meta: many resource usage improvements and consolidations

This commit is contained in:
bbedward
2025-07-24 12:44:11 -04:00
parent ee2cbd708d
commit e3e3788a37
34 changed files with 1614 additions and 1382 deletions

View File

@@ -140,6 +140,7 @@ Rectangle {
}
fillMode: Image.PreserveAspectCrop
smooth: true
cache: true
}
Rectangle {

View File

@@ -7,6 +7,18 @@ Column {
anchors.fill: parent
spacing: Theme.spacingM
Component.onCompleted: {
SysMonitorService.addRef();
SysMonitorService.addRef();
// Trigger immediate updates for both services
SysMonitorService.updateSystemStats();
}
Component.onDestruction: {
SysMonitorService.removeRef();
SysMonitorService.removeRef();
}
function formatNetworkSpeed(bytesPerSec) {
if (bytesPerSec < 1024)
return bytesPerSec.toFixed(0) + " B/s";
@@ -61,7 +73,7 @@ Column {
anchors.verticalCenter: parent.verticalCenter
Text {
text: ProcessMonitorService.totalCpuUsage.toFixed(1) + "%"
text: SysMonitorService.totalCpuUsage.toFixed(1) + "%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.primary
@@ -76,7 +88,7 @@ Column {
}
Text {
text: ProcessMonitorService.cpuCount + " cores"
text: SysMonitorService.cpuCount + " cores"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
@@ -96,7 +108,7 @@ Column {
spacing: 6
Repeater {
model: ProcessMonitorService.perCoreCpuUsage.length
model: SysMonitorService.perCoreCpuUsage.length
Row {
width: parent.width
@@ -119,11 +131,11 @@ Column {
anchors.verticalCenter: parent.verticalCenter
Rectangle {
width: parent.width * Math.min(1, ProcessMonitorService.perCoreCpuUsage[index] / 100)
width: parent.width * Math.min(1, SysMonitorService.perCoreCpuUsage[index] / 100)
height: parent.height
radius: parent.radius
color: {
const usage = ProcessMonitorService.perCoreCpuUsage[index];
const usage = SysMonitorService.perCoreCpuUsage[index];
if (usage > 80)
return Theme.error;
@@ -145,7 +157,7 @@ Column {
}
Text {
text: ProcessMonitorService.perCoreCpuUsage[index] ? ProcessMonitorService.perCoreCpuUsage[index].toFixed(0) + "%" : "0%"
text: SysMonitorService.perCoreCpuUsage[index] ? SysMonitorService.perCoreCpuUsage[index].toFixed(0) + "%" : "0%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
@@ -191,7 +203,7 @@ Column {
}
Text {
text: ProcessMonitorService.formatSystemMemory(ProcessMonitorService.usedMemoryKB) + " / " + ProcessMonitorService.formatSystemMemory(ProcessMonitorService.totalMemoryKB)
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB) + " / " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB)
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
@@ -215,11 +227,11 @@ Column {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: ProcessMonitorService.totalMemoryKB > 0 ? parent.width * (ProcessMonitorService.usedMemoryKB / ProcessMonitorService.totalMemoryKB) : 0
width: SysMonitorService.totalMemoryKB > 0 ? parent.width * (SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) : 0
height: parent.height
radius: parent.radius
color: {
const usage = ProcessMonitorService.totalMemoryKB > 0 ? (ProcessMonitorService.usedMemoryKB / ProcessMonitorService.totalMemoryKB) : 0;
const usage = SysMonitorService.totalMemoryKB > 0 ? (SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) : 0;
if (usage > 0.9)
return Theme.error;
@@ -241,7 +253,7 @@ Column {
}
Text {
text: ProcessMonitorService.totalMemoryKB > 0 ? ((ProcessMonitorService.usedMemoryKB / ProcessMonitorService.totalMemoryKB) * 100).toFixed(1) + "% used" : "No data"
text: SysMonitorService.totalMemoryKB > 0 ? ((SysMonitorService.usedMemoryKB / SysMonitorService.totalMemoryKB) * 100).toFixed(1) + "% used" : "No data"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
@@ -266,8 +278,8 @@ Column {
}
Text {
text: ProcessMonitorService.totalSwapKB > 0 ?
ProcessMonitorService.formatSystemMemory(ProcessMonitorService.usedSwapKB) + " / " + ProcessMonitorService.formatSystemMemory(ProcessMonitorService.totalSwapKB) :
text: SysMonitorService.totalSwapKB > 0 ?
SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) + " / " + SysMonitorService.formatSystemMemory(SysMonitorService.totalSwapKB) :
"No swap configured"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
@@ -292,12 +304,12 @@ Column {
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
Rectangle {
width: ProcessMonitorService.totalSwapKB > 0 ? parent.width * (ProcessMonitorService.usedSwapKB / ProcessMonitorService.totalSwapKB) : 0
width: SysMonitorService.totalSwapKB > 0 ? parent.width * (SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB) : 0
height: parent.height
radius: parent.radius
color: {
if (!ProcessMonitorService.totalSwapKB) return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3);
const usage = ProcessMonitorService.usedSwapKB / ProcessMonitorService.totalSwapKB;
if (!SysMonitorService.totalSwapKB) return Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3);
const usage = SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB;
if (usage > 0.9) return Theme.error;
if (usage > 0.7) return Theme.warning;
return Theme.info;
@@ -312,7 +324,7 @@ Column {
}
Text {
text: ProcessMonitorService.totalSwapKB > 0 ? ((ProcessMonitorService.usedSwapKB / ProcessMonitorService.totalSwapKB) * 100).toFixed(1) + "% used" : "Not available"
text: SysMonitorService.totalSwapKB > 0 ? ((SysMonitorService.usedSwapKB / SysMonitorService.totalSwapKB) * 100).toFixed(1) + "% used" : "Not available"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
@@ -363,7 +375,7 @@ Column {
}
Text {
text: formatNetworkSpeed(ProcessMonitorService.networkRxRate)
text: SysMonitorService.networkRxRate > 0 ? formatNetworkSpeed(SysMonitorService.networkRxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
@@ -381,7 +393,7 @@ Column {
}
Text {
text: formatNetworkSpeed(ProcessMonitorService.networkTxRate)
text: SysMonitorService.networkTxRate > 0 ? formatNetworkSpeed(SysMonitorService.networkTxRate) : "0 B/s"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
@@ -429,7 +441,7 @@ Column {
}
Text {
text: formatDiskSpeed(ProcessMonitorService.diskReadRate)
text: formatDiskSpeed(SysMonitorService.diskReadRate)
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText
@@ -447,7 +459,7 @@ Column {
}
Text {
text: formatDiskSpeed(ProcessMonitorService.diskWriteRate)
text: formatDiskSpeed(SysMonitorService.diskWriteRate)
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: Theme.surfaceText

View File

@@ -49,7 +49,7 @@ Rectangle {
DankIcon {
id: processIcon
name: ProcessMonitorService.getProcessIcon(process ? process.command : "")
name: SysMonitorService.getProcessIcon(process ? process.command : "")
size: Theme.iconSize - 4
color: {
if (process && process.cpu > 80)
@@ -97,7 +97,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
Text {
text: ProcessMonitorService.formatCpuUsage(process ? process.cpu : 0)
text: SysMonitorService.formatCpuUsage(process ? process.cpu : 0)
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: {
@@ -134,7 +134,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
Text {
text: ProcessMonitorService.formatMemoryUsage(process ? process.memoryKB : 0)
text: SysMonitorService.formatMemoryUsage(process ? process.memoryKB : 0)
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Bold
color: {

View File

@@ -39,7 +39,7 @@ PanelWindow {
visible: isVisible
Ref {
service: ProcessMonitorService
service: SysMonitorService
}
implicitWidth: 600

View File

@@ -7,6 +7,14 @@ Column {
id: root
property var contextMenu: null
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
Item {
id: columnHeaders
@@ -14,66 +22,129 @@ Column {
anchors.leftMargin: 8
height: 24
Text {
text: "Process"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
opacity: 0.7
Rectangle {
width: 60
height: 20
color: processHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
radius: Theme.cornerRadius
anchors.left: parent.left
anchors.leftMargin: 0 // Left align with content area
anchors.leftMargin: 0
anchors.verticalCenter: parent.verticalCenter
Text {
text: "Process"
font.pixelSize: Theme.fontSizeSmall
font.weight: SysMonitorService.sortBy === "name" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: SysMonitorService.sortBy === "name" ? 1.0 : 0.7
anchors.centerIn: parent
}
MouseArea {
id: processHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: SysMonitorService.setSortBy("name")
}
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
}
Rectangle {
width: 80
height: 20
color: "transparent"
color: cpuHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 200 // Slight adjustment to move right
anchors.rightMargin: 200
anchors.verticalCenter: parent.verticalCenter
Text {
text: "CPU"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
font.weight: SysMonitorService.sortBy === "cpu" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: 0.7
opacity: SysMonitorService.sortBy === "cpu" ? 1.0 : 0.7
anchors.centerIn: parent
}
MouseArea {
id: cpuHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: SysMonitorService.setSortBy("cpu")
}
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
}
Rectangle {
width: 80
height: 20
color: "transparent"
color: memoryHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 112 // Move right by decreasing rightMargin
anchors.rightMargin: 112
anchors.verticalCenter: parent.verticalCenter
Text {
text: "RAM"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
font.weight: SysMonitorService.sortBy === "memory" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: 0.7
opacity: SysMonitorService.sortBy === "memory" ? 1.0 : 0.7
anchors.centerIn: parent
}
MouseArea {
id: memoryHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: SysMonitorService.setSortBy("memory")
}
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
}
Text {
text: "PID"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
opacity: 0.7
Rectangle {
width: 50
horizontalAlignment: Text.AlignRight
height: 20
color: pidHeaderArea.containsMouse ? Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.08) : "transparent"
radius: Theme.cornerRadius
anchors.right: parent.right
anchors.rightMargin: 53 // Move left by increasing rightMargin
anchors.rightMargin: 53
anchors.verticalCenter: parent.verticalCenter
Text {
text: "PID"
font.pixelSize: Theme.fontSizeSmall
font.weight: SysMonitorService.sortBy === "pid" ? Font.Bold : Font.Medium
color: Theme.surfaceText
opacity: SysMonitorService.sortBy === "pid" ? 1.0 : 0.7
horizontalAlignment: Text.AlignHCenter
anchors.centerIn: parent
}
MouseArea {
id: pidHeaderArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: SysMonitorService.setSortBy("pid")
}
Behavior on color {
ColorAnimation { duration: Theme.shortDuration }
}
}
Rectangle {
@@ -86,7 +157,7 @@ Column {
anchors.verticalCenter: parent.verticalCenter
Text {
text: ProcessMonitorService.sortDescending ? "↓" : "↑"
text: SysMonitorService.sortDescending ? "↓" : "↑"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
anchors.centerIn: parent
@@ -98,7 +169,7 @@ Column {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: ProcessMonitorService.toggleSortOrder()
onClicked: SysMonitorService.toggleSortOrder()
}
Behavior on color {
@@ -123,7 +194,7 @@ Column {
id: processListView
anchors.fill: parent
model: ProcessMonitorService.processes
model: SysMonitorService.processes
spacing: 4
delegate: ProcessListItem {

View File

@@ -6,20 +6,28 @@ Row {
width: parent.width
spacing: Theme.spacingM
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
Rectangle {
width: (parent.width - Theme.spacingM * 2) / 3
height: 80
radius: Theme.cornerRadiusLarge
color: {
if (ProcessMonitorService.sortBy === "cpu")
if (SysMonitorService.sortBy === "cpu")
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16);
else if (cpuCardMouseArea.containsMouse)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
else
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08);
}
border.color: ProcessMonitorService.sortBy === "cpu" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2)
border.width: ProcessMonitorService.sortBy === "cpu" ? 2 : 1
border.color: SysMonitorService.sortBy === "cpu" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2)
border.width: SysMonitorService.sortBy === "cpu" ? 2 : 1
MouseArea {
id: cpuCardMouseArea
@@ -27,7 +35,7 @@ Row {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: ProcessMonitorService.setSortBy("cpu")
onClicked: SysMonitorService.setSortBy("cpu")
}
Column {
@@ -40,19 +48,19 @@ Row {
text: "CPU"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: ProcessMonitorService.sortBy === "cpu" ? Theme.primary : Theme.secondary
opacity: ProcessMonitorService.sortBy === "cpu" ? 1 : 0.8
color: SysMonitorService.sortBy === "cpu" ? Theme.primary : Theme.secondary
opacity: SysMonitorService.sortBy === "cpu" ? 1 : 0.8
}
Text {
text: ProcessMonitorService.totalCpuUsage.toFixed(1) + "%"
text: SysMonitorService.totalCpuUsage.toFixed(1) + "%"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
Text {
text: ProcessMonitorService.cpuCount + " cores"
text: SysMonitorService.cpuCount + " cores"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
opacity: 0.7
@@ -81,15 +89,15 @@ Row {
height: 80
radius: Theme.cornerRadiusLarge
color: {
if (ProcessMonitorService.sortBy === "memory")
if (SysMonitorService.sortBy === "memory")
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16);
else if (memoryCardMouseArea.containsMouse)
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.12);
else
return Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08);
}
border.color: ProcessMonitorService.sortBy === "memory" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.2)
border.width: ProcessMonitorService.sortBy === "memory" ? 2 : 1
border.color: SysMonitorService.sortBy === "memory" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.4) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.2)
border.width: SysMonitorService.sortBy === "memory" ? 2 : 1
MouseArea {
id: memoryCardMouseArea
@@ -97,7 +105,7 @@ Row {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: ProcessMonitorService.setSortBy("memory")
onClicked: SysMonitorService.setSortBy("memory")
}
Column {
@@ -110,19 +118,19 @@ Row {
text: "Memory"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: ProcessMonitorService.sortBy === "memory" ? Theme.primary : Theme.secondary
opacity: ProcessMonitorService.sortBy === "memory" ? 1 : 0.8
color: SysMonitorService.sortBy === "memory" ? Theme.primary : Theme.secondary
opacity: SysMonitorService.sortBy === "memory" ? 1 : 0.8
}
Text {
text: ProcessMonitorService.formatSystemMemory(ProcessMonitorService.usedMemoryKB)
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB)
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
Text {
text: "of " + ProcessMonitorService.formatSystemMemory(ProcessMonitorService.totalMemoryKB)
text: "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB)
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
opacity: 0.7
@@ -150,8 +158,8 @@ Row {
width: (parent.width - Theme.spacingM * 2) / 3
height: 80
radius: Theme.cornerRadiusLarge
color: ProcessMonitorService.totalSwapKB > 0 ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04)
border.color: ProcessMonitorService.totalSwapKB > 0 ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.2) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.12)
color: SysMonitorService.totalSwapKB > 0 ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04)
border.color: SysMonitorService.totalSwapKB > 0 ? Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.2) : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.12)
border.width: 1
Column {
@@ -164,19 +172,19 @@ Row {
text: "Swap"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: ProcessMonitorService.totalSwapKB > 0 ? Theme.warning : Theme.surfaceText
color: SysMonitorService.totalSwapKB > 0 ? Theme.warning : Theme.surfaceText
opacity: 0.8
}
Text {
text: ProcessMonitorService.totalSwapKB > 0 ? ProcessMonitorService.formatSystemMemory(ProcessMonitorService.usedSwapKB) : "None"
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) : "None"
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
Text {
text: ProcessMonitorService.totalSwapKB > 0 ? "of " + ProcessMonitorService.formatSystemMemory(ProcessMonitorService.totalSwapKB) : "No swap configured"
text: SysMonitorService.totalSwapKB > 0 ? "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalSwapKB) : "No swap configured"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
opacity: 0.7

View File

@@ -10,6 +10,14 @@ ScrollView {
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
Column {
width: parent.width
spacing: Theme.spacingM
@@ -44,26 +52,26 @@ ScrollView {
spacing: Theme.spacingS
Text {
text: SystemMonitorService.hostname
text: SysMonitorService.hostname
font.pixelSize: Theme.fontSizeXLarge
font.weight: Font.Light
color: Theme.surfaceText
}
Text {
text: SystemMonitorService.distribution + " • " + SystemMonitorService.architecture + " • " + SystemMonitorService.kernelVersion
text: SysMonitorService.distribution + " • " + SysMonitorService.architecture + " • " + SysMonitorService.kernelVersion
font.pixelSize: Theme.fontSizeMedium
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
}
Text {
text: "Up " + UserInfoService.uptime + " • Boot: " + SystemMonitorService.bootTime
text: "Up " + UserInfoService.uptime + " • Boot: " + SysMonitorService.bootTime
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
}
Text {
text: "Load: " + SystemMonitorService.loadAverage + " • " + SystemMonitorService.processCount + " processes, " + SystemMonitorService.threadCount + " threads"
text: "Load: " + SysMonitorService.loadAverage + " • " + SysMonitorService.processCount + " processes, " + SysMonitorService.threadCount + " threads"
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
}
@@ -87,7 +95,7 @@ ScrollView {
spacing: Theme.spacingS
Text {
text: SystemMonitorService.cpuModel
text: SysMonitorService.cpuModel
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
@@ -96,7 +104,7 @@ ScrollView {
}
Text {
text: SystemMonitorService.motherboard
text: SysMonitorService.motherboard
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
@@ -111,7 +119,7 @@ ScrollView {
spacing: Theme.spacingS
Text {
text: SystemMonitorService.formatMemory(SystemMonitorService.totalMemory) + " Memory"
text: SysMonitorService.formatMemory(SysMonitorService.totalMemoryMB) + " Memory"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
@@ -120,7 +128,7 @@ ScrollView {
}
Text {
text: "BIOS " + SystemMonitorService.biosVersion
text: "BIOS " + SysMonitorService.biosVersion
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText
@@ -173,13 +181,6 @@ ScrollView {
}
Text {
text: "I/O Scheduler: " + SystemMonitorService.scheduler
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
width: parent.width
elide: Text.ElideRight
}
Column {
width: parent.width
@@ -249,7 +250,7 @@ ScrollView {
Repeater {
id: diskMountRepeater
model: SystemMonitorService.diskMounts
model: SysMonitorService.diskMounts
Rectangle {
width: parent.width

View File

@@ -0,0 +1,56 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Widgets
ScrollView {
id: root
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
width: root.width - 20
spacing: Theme.spacingL
topPadding: Theme.spacingM
bottomPadding: Theme.spacingL
// Display Settings
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "monitor"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Display"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
DisplayTab {
width: parent.width
}
}
}
}

View File

@@ -0,0 +1,91 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Widgets
ScrollView {
id: root
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
width: root.width - 20
spacing: Theme.spacingL
topPadding: Theme.spacingM
bottomPadding: Theme.spacingL
// Profile Section
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "person"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Profile"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
ProfileTab {
width: parent.width
}
}
// Wallpaper Section
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "wallpaper"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Wallpaper"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
WallpaperTab {
width: parent.width
}
}
}
}

View File

@@ -43,21 +43,21 @@ Column {
visible: parent.hasImage
}
Image {
CachingImage {
id: avatarImageSource
source: {
imagePath: {
if (Prefs.profileImage === "")
return "";
if (Prefs.profileImage.startsWith("/"))
return "file://" + Prefs.profileImage;
return Prefs.profileImage;
return Prefs.profileImage;
}
smooth: true
asynchronous: true
mipmap: true
maxCacheSize: 80
cache: true
visible: false
}
@@ -223,7 +223,7 @@ Column {
id: profileBrowserLoader
active: false
FileBrowser {
DankFileBrowser {
id: profileBrowser
browserTitle: "Select Profile Image"
browserIcon: "person"

View File

@@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Widgets
@@ -8,30 +10,71 @@ Column {
property string title: ""
property string iconName: ""
property alias content: contentLoader.sourceComponent
property bool expanded: false
property bool collapsible: true
property bool lazyLoad: true
width: parent.width
spacing: Theme.spacingM
spacing: expanded ? Theme.spacingM : 0
// Section header
Row {
MouseArea {
width: parent.width
spacing: Theme.spacingS
DankIcon {
name: iconName
size: Theme.iconSize - 2
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
height: headerRow.height
enabled: collapsible
hoverEnabled: collapsible
Rectangle {
anchors.fill: parent
color: parent.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.radiusS
}
Text {
text: title
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
Row {
id: headerRow
width: parent.width
spacing: Theme.spacingS
topPadding: Theme.spacingS
bottomPadding: Theme.spacingS
DankIcon {
name: root.collapsible ? (root.expanded ? "expand_less" : "expand_more") : root.iconName
size: Theme.iconSize - 2
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
Behavior on rotation {
NumberAnimation {
duration: Appearance.anim.durations.fast
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
DankIcon {
name: root.iconName
size: Theme.iconSize - 4
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
visible: root.collapsible
}
Text {
text: root.title
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
onClicked: {
if (collapsible) {
expanded = !expanded
}
}
}
// Divider
@@ -39,6 +82,7 @@ Column {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
visible: expanded || !collapsible
}
// Content
@@ -46,6 +90,24 @@ Column {
id: contentLoader
width: parent.width
active: lazyLoad ? expanded || !collapsible : true
visible: expanded || !collapsible
asynchronous: true
Behavior on opacity {
NumberAnimation {
duration: Appearance.anim.durations.normal
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
}
}
opacity: visible ? 1 : 0
}
Component.onCompleted: {
if (!collapsible) {
expanded = true
}
}
}

View File

@@ -0,0 +1,91 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Widgets
ScrollView {
id: root
clip: true
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Column {
width: root.width - 20
spacing: Theme.spacingL
topPadding: Theme.spacingM
bottomPadding: Theme.spacingL
// Top Bar Widgets
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "widgets"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Top Bar Widgets"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
WidgetsTab {
width: parent.width
}
}
// Workspaces
Column {
width: parent.width
spacing: Theme.spacingM
Row {
spacing: Theme.spacingS
DankIcon {
name: "tab"
size: Theme.iconSize
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: "Workspaces"
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
WorkspaceTab {
width: parent.width
}
}
}
}

View File

@@ -270,7 +270,13 @@ Column {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
Theme.switchTheme(10, true);
if (ToastService.wallpaperErrorStatus === "matugen_missing") {
ToastService.showError("matugen not found - install matugen package for dynamic theming");
} else if (ToastService.wallpaperErrorStatus === "error") {
ToastService.showError("Wallpaper processing failed - check wallpaper path");
} else {
Theme.switchTheme(10, true);
}
}
}

View File

@@ -3,6 +3,7 @@ import QtQuick.Controls
import QtQuick.Effects
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Column {
@@ -36,12 +37,13 @@ Column {
border.color: Theme.outline
border.width: 1
Image {
CachingImage {
anchors.fill: parent
anchors.margins: 1
source: Prefs.wallpaperPath ? "file://" + Prefs.wallpaperPath : ""
imagePath: Prefs.wallpaperPath || ""
fillMode: Image.PreserveAspectCrop
visible: Prefs.wallpaperPath !== ""
maxCacheSize: 120
layer.enabled: true
layer.effect: MultiEffect {
maskEnabled: true
@@ -204,21 +206,32 @@ Column {
DankToggle {
id: toggle
anchors.verticalCenter: parent.verticalCenter
checked: Prefs.wallpaperDynamicTheming
onCheckedChanged: {
if (activeFocus) {
Prefs.setWallpaperDynamicTheming(checked);
checked: Theme.isDynamicTheme
enabled: ToastService.wallpaperErrorStatus !== "matugen_missing"
onToggled: (toggled) => {
if (toggled) {
Theme.switchTheme(10, true)
} else {
Theme.switchTheme(0)
}
}
}
}
StyledText {
text: "matugen not detected"
font.pixelSize: Theme.fontSizeSmall
color: Theme.error
visible: ToastService.wallpaperErrorStatus === "matugen_missing"
width: parent.width
}
}
LazyLoader {
id: wallpaperBrowserLoader
active: false
FileBrowser {
DankFileBrowser {
id: wallpaperBrowser
browserTitle: "Select Wallpaper"
browserIcon: "wallpaper"

View File

@@ -24,12 +24,10 @@ Item {
onExited: (exitCode) => {
root.cavaAvailable = exitCode === 0;
if (root.cavaAvailable) {
console.log("cava found - enabling real audio visualization");
cavaProcess.running = Qt.binding(() => {
return root.hasActiveMedia && root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing;
});
} else {
console.log("cava not found - using fallback animation");
fallbackTimer.running = Qt.binding(() => {
return root.hasActiveMedia && root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing;
});

View File

@@ -17,6 +17,14 @@ Rectangle {
radius: Theme.cornerRadius
color: cpuArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08)
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
MouseArea {
id: cpuArea
@@ -24,7 +32,7 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
ProcessMonitorService.setSortBy("cpu");
SysMonitorService.setSortBy("cpu");
if (root.toggleProcessList)
root.toggleProcessList();
}
@@ -38,10 +46,10 @@ Rectangle {
name: "memory"
size: Theme.iconSize - 8
color: {
if (SystemMonitorService.cpuUsage > 80)
if (SysMonitorService.cpuUsage > 80)
return Theme.error;
if (SystemMonitorService.cpuUsage > 60)
if (SysMonitorService.cpuUsage > 60)
return Theme.warning;
return Theme.surfaceText;
@@ -50,7 +58,7 @@ Rectangle {
}
Text {
text: (SystemMonitorService.cpuUsage || 0).toFixed(0) + "%"
text: (SysMonitorService.cpuUsage || 0).toFixed(0) + "%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText

View File

@@ -17,6 +17,14 @@ Rectangle {
radius: Theme.cornerRadius
color: ramArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.16) : Qt.rgba(Theme.secondary.r, Theme.secondary.g, Theme.secondary.b, 0.08)
Component.onCompleted: {
SysMonitorService.addRef();
}
Component.onDestruction: {
SysMonitorService.removeRef();
}
MouseArea {
id: ramArea
@@ -24,7 +32,7 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
ProcessMonitorService.setSortBy("memory");
SysMonitorService.setSortBy("memory");
if (root.toggleProcessList)
root.toggleProcessList();
}
@@ -38,10 +46,10 @@ Rectangle {
name: "developer_board"
size: Theme.iconSize - 8
color: {
if (SystemMonitorService.memoryUsage > 90)
if (SysMonitorService.memoryUsage > 90)
return Theme.error;
if (SystemMonitorService.memoryUsage > 75)
if (SysMonitorService.memoryUsage > 75)
return Theme.warning;
return Theme.surfaceText;
@@ -50,7 +58,7 @@ Rectangle {
}
Text {
text: (SystemMonitorService.memoryUsage || 0).toFixed(0) + "%"
text: (SysMonitorService.memoryUsage || 0).toFixed(0) + "%"
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.surfaceText

View File

@@ -22,30 +22,43 @@ Rectangle {
Repeater {
model: SystemTray.items
delegate: Rectangle {
delegate: Item {
property var trayItem: modelData
property string iconSource: {
let icon = trayItem && trayItem.icon;
if (typeof icon === 'string' || icon instanceof String) {
if (icon.includes("?path=")) {
const [name, path] = icon.split("?path=");
const fileName = name.substring(name.lastIndexOf("/") + 1);
return `file://${path}/${fileName}`;
}
return icon;
}
return "";
}
width: 24
height: 24
radius: Theme.cornerRadiusSmall
color: trayItemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Rectangle {
anchors.fill: parent
radius: Theme.cornerRadiusSmall
color: trayItemArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
Behavior on color {
enabled: trayItemArea.containsMouse !== undefined
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Image {
anchors.centerIn: parent
width: 18
height: 18
source: {
let icon = trayItem && trayItem.icon;
if (typeof icon === 'string' || icon instanceof String) {
if (icon.includes("?path=")) {
const [name, path] = icon.split("?path=");
const fileName = name.substring(name.lastIndexOf("/") + 1);
return `file://${path}/${fileName}`;
}
return icon;
}
return ""; // Return empty string if icon is not a string
}
source: parent.iconSource
asynchronous: true
smooth: true
fillMode: Image.PreserveAspectFit
@@ -53,51 +66,23 @@ Rectangle {
MouseArea {
id: trayItemArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: (mouse) => {
if (!trayItem)
return ;
if (!trayItem) return;
if (mouse.button === Qt.LeftButton) {
if (!trayItem.onlyMenu)
trayItem.activate();
} else if (mouse.button === Qt.RightButton) {
if (trayItem && trayItem.hasMenu)
customTrayMenu.showMenu(mouse.x, mouse.y);
if (trayItem && trayItem.hasMenu) {
root.menuRequested(null, trayItem, mouse.x, mouse.y);
}
}
}
}
QtObject {
id: customTrayMenu
property bool menuVisible: false
function showMenu(x, y) {
root.menuRequested(customTrayMenu, trayItem, x, y);
menuVisible = true;
}
function hideMenu() {
menuVisible = false;
}
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}

View File

@@ -234,16 +234,24 @@ PanelWindow {
}
CpuMonitor {
Loader {
anchors.verticalCenter: parent.verticalCenter
visible: Prefs.showSystemResources
toggleProcessList: () => processListPopout.toggle()
active: Prefs.showSystemResources
sourceComponent: Component {
CpuMonitor {
toggleProcessList: () => processListPopout.toggle()
}
}
}
RamMonitor {
Loader {
anchors.verticalCenter: parent.verticalCenter
visible: Prefs.showSystemResources
toggleProcessList: () => processListPopout.toggle()
active: Prefs.showSystemResources
sourceComponent: Component {
RamMonitor {
toggleProcessList: () => processListPopout.toggle()
}
}
}
NotificationCenterButton {

View File

@@ -5,59 +5,133 @@ import Quickshell.Widgets
import qs.Common
import qs.Widgets
Variants {
model: Quickshell.screens
LazyLoader {
active: Prefs.wallpaperPath !== ""
PanelWindow {
id: wallpaperWindow
Variants {
model: Quickshell.screens
property var modelData
PanelWindow {
id: wallpaperWindow
screen: modelData
required property var modelData
WlrLayershell.layer: WlrLayer.Background
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
screen: modelData
anchors.top: true
anchors.bottom: true
anchors.left: true
anchors.right: true
WlrLayershell.layer: WlrLayer.Background
WlrLayershell.exclusionMode: ExclusionMode.Ignore
visible: true
color: "transparent"
anchors.top: true
anchors.bottom: true
anchors.left: true
anchors.right: true
Image {
id: wallpaperImage
color: "black"
anchors.fill: parent
source: Prefs.wallpaperPath ? "file://" + Prefs.wallpaperPath : ""
fillMode: Image.PreserveAspectCrop
visible: Prefs.wallpaperPath !== ""
smooth: true
cache: true
Item {
id: root
anchors.fill: parent
// Smooth transition when wallpaper changes
Behavior on opacity {
NumberAnimation {
duration: Appearance.anim.durations.normal
easing.type: Easing.BezierSpline
easing.bezierCurve: Appearance.anim.curves.standard
property string source: Prefs.wallpaperPath || ""
property Image current: one
onSourceChanged: {
if (!source)
current = null;
else if (current === one)
two.update();
else
one.update();
}
Loader {
anchors.fill: parent
active: !root.source
asynchronous: true
sourceComponent: Rectangle {
color: Theme.surface
Row {
anchors.centerIn: parent
spacing: Theme.spacingL
DankIcon {
name: "sentiment_stressed"
color: Theme.surfaceVariantText
size: Theme.iconSize * 5
anchors.verticalCenter: parent.verticalCenter
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
StyledText {
text: "Wallpaper missing?"
color: Theme.surfaceVariantText
font.pixelSize: Theme.fontSizeXLarge * 2
font.weight: Font.Bold
}
StyledText {
text: "Set wallpaper in Settings"
color: Theme.primary
font.pixelSize: Theme.fontSizeLarge
}
}
}
}
}
Img {
id: one
}
Img {
id: two
}
component Img: Image {
id: img
function update(): void {
source = "";
source = root.source;
}
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
smooth: true
asynchronous: true
cache: true
opacity: 0
onStatusChanged: {
if (status === Image.Ready)
root.current = this;
}
states: State {
name: "visible"
when: root.current === img
PropertyChanges {
img.opacity: 1
}
}
transitions: Transition {
NumberAnimation {
target: img
properties: "opacity"
duration: Theme.mediumDuration
easing.type: Easing.OutCubic
}
}
}
}
onStatusChanged: {
if (status === Image.Error) {
console.warn("Failed to load wallpaper:", source);
}
}
}
// Fallback background color when no wallpaper is set
StyledRect {
anchors.fill: parent
color: Theme.surface
visible: !wallpaperImage.visible
}
}
}