mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
feat: add temperature widgets, separate ram/cpu widgets, update
calculations - make CPU calculations per-process mirror gnome (of all CPUs)
This commit is contained in:
@@ -29,7 +29,11 @@ Singleton {
|
||||
property bool showWeather: true
|
||||
property bool showMusic: true
|
||||
property bool showClipboard: true
|
||||
property bool showSystemResources: true
|
||||
property bool showCpuUsage: true
|
||||
property bool showMemUsage: true
|
||||
property bool showCpuTemp: true
|
||||
property bool showGpuTemp: true
|
||||
property int selectedGpuIndex: 0
|
||||
property bool showSystemTray: true
|
||||
property bool showClock: true
|
||||
property bool showNotificationButton: true
|
||||
@@ -41,13 +45,14 @@ Singleton {
|
||||
property bool mediaCompactMode: false
|
||||
property var topBarLeftWidgets: ["launcherButton", "workspaceSwitcher", "focusedWindow"]
|
||||
property var topBarCenterWidgets: ["music", "clock", "weather"]
|
||||
property var topBarRightWidgets: ["systemTray", "clipboard", "systemResources", "notificationButton", "battery", "controlCenterButton"]
|
||||
property var topBarRightWidgets: ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"]
|
||||
|
||||
property alias topBarLeftWidgetsModel: leftWidgetsModel
|
||||
property alias topBarCenterWidgetsModel: centerWidgetsModel
|
||||
property alias topBarRightWidgetsModel: rightWidgetsModel
|
||||
|
||||
signal forceTopBarLayoutRefresh()
|
||||
signal widgetDataChanged()
|
||||
|
||||
ListModel {
|
||||
id: leftWidgetsModel
|
||||
@@ -150,7 +155,11 @@ Singleton {
|
||||
showWeather = settings.showWeather !== undefined ? settings.showWeather : true;
|
||||
showMusic = settings.showMusic !== undefined ? settings.showMusic : true;
|
||||
showClipboard = settings.showClipboard !== undefined ? settings.showClipboard : true;
|
||||
showSystemResources = settings.showSystemResources !== undefined ? settings.showSystemResources : true;
|
||||
showCpuUsage = settings.showCpuUsage !== undefined ? settings.showCpuUsage : true;
|
||||
showMemUsage = settings.showMemUsage !== undefined ? settings.showMemUsage : true;
|
||||
showCpuTemp = settings.showCpuTemp !== undefined ? settings.showCpuTemp : true;
|
||||
showGpuTemp = settings.showGpuTemp !== undefined ? settings.showGpuTemp : true;
|
||||
selectedGpuIndex = settings.selectedGpuIndex !== undefined ? settings.selectedGpuIndex : 0;
|
||||
showSystemTray = settings.showSystemTray !== undefined ? settings.showSystemTray : true;
|
||||
showClock = settings.showClock !== undefined ? settings.showClock : true;
|
||||
showNotificationButton = settings.showNotificationButton !== undefined ? settings.showNotificationButton : true;
|
||||
@@ -167,7 +176,7 @@ Singleton {
|
||||
} else {
|
||||
var leftWidgets = settings.topBarLeftWidgets !== undefined ? settings.topBarLeftWidgets : ["launcherButton", "workspaceSwitcher", "focusedWindow"];
|
||||
var centerWidgets = settings.topBarCenterWidgets !== undefined ? settings.topBarCenterWidgets : ["music", "clock", "weather"];
|
||||
var rightWidgets = settings.topBarRightWidgets !== undefined ? settings.topBarRightWidgets : ["systemTray", "clipboard", "systemResources", "notificationButton", "battery", "controlCenterButton"];
|
||||
var rightWidgets = settings.topBarRightWidgets !== undefined ? settings.topBarRightWidgets : ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"];
|
||||
|
||||
topBarLeftWidgets = leftWidgets;
|
||||
topBarCenterWidgets = centerWidgets;
|
||||
@@ -227,7 +236,11 @@ Singleton {
|
||||
"showWeather": showWeather,
|
||||
"showMusic": showMusic,
|
||||
"showClipboard": showClipboard,
|
||||
"showSystemResources": showSystemResources,
|
||||
"showCpuUsage": showCpuUsage,
|
||||
"showMemUsage": showMemUsage,
|
||||
"showCpuTemp": showCpuTemp,
|
||||
"showGpuTemp": showGpuTemp,
|
||||
"selectedGpuIndex": selectedGpuIndex,
|
||||
"showSystemTray": showSystemTray,
|
||||
"showClock": showClock,
|
||||
"showNotificationButton": showNotificationButton,
|
||||
@@ -370,8 +383,28 @@ Singleton {
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setShowSystemResources(enabled) {
|
||||
showSystemResources = enabled;
|
||||
function setShowCpuUsage(enabled) {
|
||||
showCpuUsage = enabled;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setShowMemUsage(enabled) {
|
||||
showMemUsage = enabled;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setShowCpuTemp(enabled) {
|
||||
showCpuTemp = enabled;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setShowGpuTemp(enabled) {
|
||||
showGpuTemp = enabled;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
function setSelectedGpuIndex(index) {
|
||||
selectedGpuIndex = index;
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
@@ -429,19 +462,25 @@ Singleton {
|
||||
var widgetId = typeof order[i] === "string" ? order[i] : order[i].id;
|
||||
var enabled = typeof order[i] === "string" ? true : order[i].enabled;
|
||||
var size = typeof order[i] === "string" ? undefined : order[i].size;
|
||||
var selectedGpuIndex = typeof order[i] === "string" ? undefined : order[i].selectedGpuIndex;
|
||||
|
||||
var item = {"widgetId": widgetId, "enabled": enabled};
|
||||
if (size !== undefined) {
|
||||
item.size = size;
|
||||
}
|
||||
if (selectedGpuIndex !== undefined) {
|
||||
item.selectedGpuIndex = selectedGpuIndex;
|
||||
}
|
||||
listModel.append(item);
|
||||
}
|
||||
// Emit signal to notify widgets that data has changed
|
||||
widgetDataChanged();
|
||||
}
|
||||
|
||||
function resetTopBarWidgetsToDefault() {
|
||||
var defaultLeft = ["launcherButton", "workspaceSwitcher", "focusedWindow"];
|
||||
var defaultCenter = ["music", "clock", "weather"];
|
||||
var defaultRight = ["systemTray", "clipboard", "systemResources", "notificationButton", "battery", "controlCenterButton"];
|
||||
var defaultRight = ["systemTray", "clipboard", "cpuUsage", "memUsage", "notificationButton", "battery", "controlCenterButton"];
|
||||
|
||||
topBarLeftWidgets = defaultLeft;
|
||||
topBarCenterWidgets = defaultCenter;
|
||||
@@ -457,7 +496,10 @@ Singleton {
|
||||
showWeather = true;
|
||||
showMusic = true;
|
||||
showClipboard = true;
|
||||
showSystemResources = true;
|
||||
showCpuUsage = true;
|
||||
showMemUsage = true;
|
||||
showCpuTemp = true;
|
||||
showGpuTemp = true;
|
||||
showSystemTray = true;
|
||||
showClock = true;
|
||||
showNotificationButton = true;
|
||||
|
||||
@@ -354,6 +354,10 @@ Singleton {
|
||||
property color info: "#2196F3"
|
||||
property color error: "#F2B8B5"
|
||||
|
||||
// Temperature-specific colors
|
||||
property color tempWarning: "#ff9933" // Balanced orange for warm temperatures
|
||||
property color tempDanger: "#ff5555" // Balanced red for dangerous temperatures
|
||||
|
||||
property color primaryHover: Qt.rgba(primary.r, primary.g, primary.b, 0.12)
|
||||
property color primaryHoverLight: Qt.rgba(primary.r, primary.g, primary.b, 0.08)
|
||||
property color primaryPressed: Qt.rgba(primary.r, primary.g, primary.b, 0.16)
|
||||
|
||||
@@ -285,7 +285,6 @@ DankModal {
|
||||
|
||||
DankListView {
|
||||
id: resultsList
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
property int itemHeight: 60
|
||||
property int iconSize: 40
|
||||
|
||||
@@ -370,7 +370,6 @@ PanelWindow {
|
||||
|
||||
DankListView {
|
||||
id: appList
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
property int itemHeight: 72
|
||||
property int iconSize: 56
|
||||
|
||||
@@ -41,7 +41,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: outputColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: outputColumn
|
||||
@@ -68,7 +67,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: inputColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: inputColumn
|
||||
|
||||
@@ -19,7 +19,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
|
||||
@@ -28,7 +28,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
|
||||
@@ -51,12 +51,44 @@ Row {
|
||||
opacity: SysMonitorService.sortBy === "cpu" ? 1 : 0.8
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.totalCpuUsage.toFixed(1) + "%"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.totalCpuUsage.toFixed(1) + "%"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: 20
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) {
|
||||
return "--°";
|
||||
}
|
||||
return Math.round(SysMonitorService.cpuTemperature) + "°";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Medium
|
||||
color: {
|
||||
if (SysMonitorService.cpuTemperature > 80)
|
||||
return Theme.error;
|
||||
if (SysMonitorService.cpuTemperature > 60)
|
||||
return Theme.warning;
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
@@ -123,16 +155,44 @@ Row {
|
||||
opacity: SysMonitorService.sortBy === "memory" ? 1 : 0.8
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB)
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.formatSystemMemory(SysMonitorService.usedMemoryKB)
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 1
|
||||
height: 20
|
||||
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.3)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: SysMonitorService.totalSwapKB > 0
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) : ""
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Medium
|
||||
color: SysMonitorService.usedSwapKB > 0 ? Theme.warning : Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: SysMonitorService.totalSwapKB > 0
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB)
|
||||
text: {
|
||||
if (SysMonitorService.totalSwapKB > 0) {
|
||||
return "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB) + " + swap";
|
||||
}
|
||||
return "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalMemoryKB);
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.family: SettingsData.monoFontFamily
|
||||
color: Theme.surfaceText
|
||||
@@ -161,8 +221,8 @@ Row {
|
||||
width: (parent.width - Theme.spacingM * 2) / 3
|
||||
height: 80
|
||||
radius: Theme.cornerRadiusLarge
|
||||
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)
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
|
||||
border.color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.2)
|
||||
border.width: 1
|
||||
|
||||
Column {
|
||||
@@ -172,23 +232,74 @@ Row {
|
||||
spacing: 2
|
||||
|
||||
StyledText {
|
||||
text: "Swap"
|
||||
text: "Graphics"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: SysMonitorService.totalSwapKB > 0 ? Theme.warning : Theme.surfaceText
|
||||
color: Theme.secondary
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.totalSwapKB > 0 ? SysMonitorService.formatSystemMemory(SysMonitorService.usedSwapKB) : "None"
|
||||
text: {
|
||||
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) {
|
||||
return "None";
|
||||
}
|
||||
if (SysMonitorService.availableGpus.length === 1) {
|
||||
var gpu = SysMonitorService.availableGpus[0];
|
||||
var temp = gpu.temperature;
|
||||
var tempText = (temp === undefined || temp === null || temp === 0) ? "--°" : Math.round(temp) + "°";
|
||||
return tempText;
|
||||
}
|
||||
// Multiple GPUs - show average temp
|
||||
var totalTemp = 0;
|
||||
var validTemps = 0;
|
||||
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
|
||||
var temp = SysMonitorService.availableGpus[i].temperature;
|
||||
if (temp !== undefined && temp !== null && temp > 0) {
|
||||
totalTemp += temp;
|
||||
validTemps++;
|
||||
}
|
||||
}
|
||||
if (validTemps > 0) {
|
||||
return Math.round(totalTemp / validTemps) + "°";
|
||||
}
|
||||
return "--°";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.family: SettingsData.monoFontFamily
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
color: {
|
||||
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) {
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
if (SysMonitorService.availableGpus.length === 1) {
|
||||
var temp = SysMonitorService.availableGpus[0].temperature || 0;
|
||||
if (temp > 80) return Theme.tempDanger;
|
||||
if (temp > 60) return Theme.tempWarning;
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
// Multiple GPUs - get max temp for coloring
|
||||
var maxTemp = 0;
|
||||
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
|
||||
var temp = SysMonitorService.availableGpus[i].temperature || 0;
|
||||
if (temp > maxTemp) maxTemp = temp;
|
||||
}
|
||||
if (maxTemp > 80) return Theme.tempDanger;
|
||||
if (maxTemp > 60) return Theme.tempWarning;
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: SysMonitorService.totalSwapKB > 0 ? "of " + SysMonitorService.formatSystemMemory(SysMonitorService.totalSwapKB) : "No swap configured"
|
||||
text: {
|
||||
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) {
|
||||
return "No GPUs detected";
|
||||
}
|
||||
if (SysMonitorService.availableGpus.length === 1) {
|
||||
return SysMonitorService.availableGpus[0].driver.toUpperCase();
|
||||
}
|
||||
return SysMonitorService.availableGpus.length + " GPUs detected";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.family: SettingsData.monoFontFamily
|
||||
color: Theme.surfaceText
|
||||
|
||||
@@ -15,7 +15,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
|
||||
@@ -14,7 +14,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
|
||||
@@ -20,7 +20,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
|
||||
@@ -13,7 +13,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
|
||||
@@ -49,11 +49,29 @@ Item {
|
||||
"icon": "content_paste",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "systemResources",
|
||||
"text": "System Resources",
|
||||
"description": "CPU and memory usage indicators",
|
||||
"id": "cpuUsage",
|
||||
"text": "CPU Usage",
|
||||
"description": "CPU usage indicator",
|
||||
"icon": "memory",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "memUsage",
|
||||
"text": "Memory Usage",
|
||||
"description": "Memory usage indicator",
|
||||
"icon": "storage",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "cpuTemp",
|
||||
"text": "CPU Temperature",
|
||||
"description": "CPU temperature display",
|
||||
"icon": "device_thermostat",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "gpuTemp",
|
||||
"text": "GPU Temperature",
|
||||
"description": "GPU temperature display",
|
||||
"icon": "auto_awesome_mosaic",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "systemTray",
|
||||
"text": "System Tray",
|
||||
@@ -127,7 +145,10 @@ Item {
|
||||
"id": "clipboard",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "systemResources",
|
||||
"id": "cpuUsage",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "memUsage",
|
||||
"enabled": true
|
||||
}, {
|
||||
"id": "notificationButton",
|
||||
@@ -147,6 +168,8 @@ Item {
|
||||
};
|
||||
if (widgetId === "spacer")
|
||||
widgetObj.size = 20;
|
||||
if (widgetId === "gpuTemp")
|
||||
widgetObj.selectedGpuIndex = 0;
|
||||
|
||||
var widgets = [];
|
||||
if (targetSection === "left") {
|
||||
@@ -164,28 +187,25 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
function removeWidgetFromSection(sectionId, itemId) {
|
||||
function removeWidgetFromSection(sectionId, widgetIndex) {
|
||||
var widgets = [];
|
||||
if (sectionId === "left") {
|
||||
widgets = SettingsData.topBarLeftWidgets.slice();
|
||||
widgets = widgets.filter((widget) => {
|
||||
var widgetId = typeof widget === "string" ? widget : widget.id;
|
||||
return widgetId !== itemId;
|
||||
});
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
widgets.splice(widgetIndex, 1);
|
||||
}
|
||||
SettingsData.setTopBarLeftWidgets(widgets);
|
||||
} else if (sectionId === "center") {
|
||||
widgets = SettingsData.topBarCenterWidgets.slice();
|
||||
widgets = widgets.filter((widget) => {
|
||||
var widgetId = typeof widget === "string" ? widget : widget.id;
|
||||
return widgetId !== itemId;
|
||||
});
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
widgets.splice(widgetIndex, 1);
|
||||
}
|
||||
SettingsData.setTopBarCenterWidgets(widgets);
|
||||
} else if (sectionId === "right") {
|
||||
widgets = SettingsData.topBarRightWidgets.slice();
|
||||
widgets = widgets.filter((widget) => {
|
||||
var widgetId = typeof widget === "string" ? widget : widget.id;
|
||||
return widgetId !== itemId;
|
||||
});
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
widgets.splice(widgetIndex, 1);
|
||||
}
|
||||
SettingsData.setTopBarRightWidgets(widgets);
|
||||
}
|
||||
}
|
||||
@@ -208,7 +228,8 @@ Item {
|
||||
} : {
|
||||
"id": widget.id,
|
||||
"enabled": enabled,
|
||||
"size": widget.size
|
||||
"size": widget.size,
|
||||
"selectedGpuIndex": widget.selectedGpuIndex
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -249,7 +270,8 @@ Item {
|
||||
} : {
|
||||
"id": widget.id,
|
||||
"enabled": widget.enabled,
|
||||
"size": newSize
|
||||
"size": newSize,
|
||||
"selectedGpuIndex": widget.selectedGpuIndex
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -262,6 +284,37 @@ Item {
|
||||
SettingsData.setTopBarRightWidgets(widgets);
|
||||
}
|
||||
|
||||
function handleGpuSelectionChanged(sectionId, widgetIndex, selectedGpuIndex) {
|
||||
var widgets = [];
|
||||
if (sectionId === "left")
|
||||
widgets = SettingsData.topBarLeftWidgets.slice();
|
||||
else if (sectionId === "center")
|
||||
widgets = SettingsData.topBarCenterWidgets.slice();
|
||||
else if (sectionId === "right")
|
||||
widgets = SettingsData.topBarRightWidgets.slice();
|
||||
|
||||
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
|
||||
var widget = widgets[widgetIndex];
|
||||
widgets[widgetIndex] = typeof widget === "string" ? {
|
||||
"id": widget,
|
||||
"enabled": true,
|
||||
"selectedGpuIndex": selectedGpuIndex
|
||||
} : {
|
||||
"id": widget.id,
|
||||
"enabled": widget.enabled,
|
||||
"size": widget.size,
|
||||
"selectedGpuIndex": selectedGpuIndex
|
||||
};
|
||||
}
|
||||
|
||||
if (sectionId === "left")
|
||||
SettingsData.setTopBarLeftWidgets(widgets);
|
||||
else if (sectionId === "center")
|
||||
SettingsData.setTopBarCenterWidgets(widgets);
|
||||
else if (sectionId === "right")
|
||||
SettingsData.setTopBarRightWidgets(widgets);
|
||||
}
|
||||
|
||||
function getItemsForSection(sectionId) {
|
||||
var widgets = [];
|
||||
var widgetData = [];
|
||||
@@ -275,6 +328,7 @@ Item {
|
||||
var widgetId = typeof widget === "string" ? widget : widget.id;
|
||||
var widgetEnabled = typeof widget === "string" ? true : widget.enabled;
|
||||
var widgetSize = typeof widget === "string" ? undefined : widget.size;
|
||||
var widgetSelectedGpuIndex = typeof widget === "string" ? undefined : widget.selectedGpuIndex;
|
||||
var widgetDef = baseWidgetDefinitions.find((w) => {
|
||||
return w.id === widgetId;
|
||||
});
|
||||
@@ -284,6 +338,8 @@ Item {
|
||||
item.enabled = widgetEnabled;
|
||||
if (widgetSize !== undefined)
|
||||
item.size = widgetSize;
|
||||
if (widgetSelectedGpuIndex !== undefined)
|
||||
item.selectedGpuIndex = widgetSelectedGpuIndex;
|
||||
|
||||
widgets.push(item);
|
||||
}
|
||||
@@ -338,7 +394,6 @@ Item {
|
||||
clip: true
|
||||
contentHeight: mainColumn.height
|
||||
contentWidth: width
|
||||
mouseWheelSpeed: 20
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
@@ -487,7 +542,7 @@ Item {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingL
|
||||
|
||||
DankSections {
|
||||
WidgetsTabSection {
|
||||
width: parent.width
|
||||
title: "Left Section"
|
||||
titleIcon: "format_align_left"
|
||||
@@ -505,8 +560,8 @@ Item {
|
||||
widgetSelectionPopup.targetSection = sectionId;
|
||||
widgetSelectionPopup.safeOpen();
|
||||
}
|
||||
onRemoveWidget: (sectionId, itemId) => {
|
||||
widgetsTab.removeWidgetFromSection(sectionId, itemId);
|
||||
onRemoveWidget: (sectionId, widgetIndex) => {
|
||||
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex);
|
||||
}
|
||||
onSpacerSizeChanged: (sectionId, itemId, newSize) => {
|
||||
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize);
|
||||
@@ -518,9 +573,12 @@ Item {
|
||||
SettingsData.setMediaCompactMode(enabled);
|
||||
}
|
||||
}
|
||||
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
|
||||
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
DankSections {
|
||||
WidgetsTabSection {
|
||||
width: parent.width
|
||||
title: "Center Section"
|
||||
titleIcon: "format_align_center"
|
||||
@@ -538,8 +596,8 @@ Item {
|
||||
widgetSelectionPopup.targetSection = sectionId;
|
||||
widgetSelectionPopup.safeOpen();
|
||||
}
|
||||
onRemoveWidget: (sectionId, itemId) => {
|
||||
widgetsTab.removeWidgetFromSection(sectionId, itemId);
|
||||
onRemoveWidget: (sectionId, widgetIndex) => {
|
||||
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex);
|
||||
}
|
||||
onSpacerSizeChanged: (sectionId, itemId, newSize) => {
|
||||
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize);
|
||||
@@ -551,9 +609,12 @@ Item {
|
||||
SettingsData.setMediaCompactMode(enabled);
|
||||
}
|
||||
}
|
||||
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
|
||||
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
DankSections {
|
||||
WidgetsTabSection {
|
||||
width: parent.width
|
||||
title: "Right Section"
|
||||
titleIcon: "format_align_right"
|
||||
@@ -571,8 +632,8 @@ Item {
|
||||
widgetSelectionPopup.targetSection = sectionId;
|
||||
widgetSelectionPopup.safeOpen();
|
||||
}
|
||||
onRemoveWidget: (sectionId, itemId) => {
|
||||
widgetsTab.removeWidgetFromSection(sectionId, itemId);
|
||||
onRemoveWidget: (sectionId, widgetIndex) => {
|
||||
widgetsTab.removeWidgetFromSection(sectionId, widgetIndex);
|
||||
}
|
||||
onSpacerSizeChanged: (sectionId, itemId, newSize) => {
|
||||
widgetsTab.handleSpacerSizeChanged(sectionId, itemId, newSize);
|
||||
@@ -584,6 +645,9 @@ Item {
|
||||
SettingsData.setMediaCompactMode(enabled);
|
||||
}
|
||||
}
|
||||
onGpuSelectionChanged: (sectionId, widgetIndex, selectedIndex) => {
|
||||
widgetsTab.handleGpuSelectionChanged(sectionId, widgetIndex, selectedIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
import qs.Services
|
||||
|
||||
Column {
|
||||
id: root
|
||||
@@ -15,9 +16,10 @@ Column {
|
||||
signal itemEnabledChanged(string sectionId, string itemId, bool enabled)
|
||||
signal itemOrderChanged(var newOrder)
|
||||
signal addWidget(string sectionId)
|
||||
signal removeWidget(string sectionId, string itemId)
|
||||
signal removeWidget(string sectionId, int widgetIndex)
|
||||
signal spacerSizeChanged(string sectionId, string itemId, int newSize)
|
||||
signal compactModeChanged(string widgetId, bool enabled)
|
||||
signal gpuSelectionChanged(string sectionId, int widgetIndex, int selectedIndex)
|
||||
|
||||
width: parent.width
|
||||
height: implicitHeight
|
||||
@@ -133,6 +135,41 @@ Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Item {
|
||||
width: 120
|
||||
height: 32
|
||||
visible: modelData.id === "gpuTemp"
|
||||
|
||||
DankDropdown {
|
||||
id: gpuDropdown
|
||||
anchors.fill: parent
|
||||
currentValue: {
|
||||
var selectedIndex = modelData.selectedGpuIndex !== undefined ? modelData.selectedGpuIndex : 0;
|
||||
if (SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > selectedIndex && selectedIndex >= 0) {
|
||||
var gpu = SysMonitorService.availableGpus[selectedIndex];
|
||||
return gpu.driver.toUpperCase() + " (" + Math.round(gpu.temperature || 0) + "°C)";
|
||||
}
|
||||
return SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > 0 ? SysMonitorService.availableGpus[0].driver.toUpperCase() + " (" + Math.round(SysMonitorService.availableGpus[0].temperature || 0) + "°C)" : "";
|
||||
}
|
||||
options: {
|
||||
var gpuOptions = [];
|
||||
if (SysMonitorService.availableGpus && SysMonitorService.availableGpus.length > 0) {
|
||||
for (var i = 0; i < SysMonitorService.availableGpus.length; i++) {
|
||||
var gpu = SysMonitorService.availableGpus[i];
|
||||
gpuOptions.push(gpu.driver.toUpperCase() + " (" + Math.round(gpu.temperature || 0) + "°C)");
|
||||
}
|
||||
}
|
||||
return gpuOptions;
|
||||
}
|
||||
onValueChanged: (value) => {
|
||||
var gpuIndex = options.indexOf(value);
|
||||
if (gpuIndex >= 0) {
|
||||
root.gpuSelectionChanged(root.sectionId, index, gpuIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 32
|
||||
height: 32
|
||||
@@ -240,7 +277,7 @@ Column {
|
||||
iconSize: 18
|
||||
iconColor: Theme.error
|
||||
onClicked: {
|
||||
root.removeWidget(root.sectionId, modelData.id);
|
||||
root.removeWidget(root.sectionId, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,10 @@ Rectangle {
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (SysMonitorService.cpuUsage > 80)
|
||||
return Theme.error;
|
||||
return Theme.tempDanger;
|
||||
|
||||
if (SysMonitorService.cpuUsage > 60)
|
||||
return Theme.warning;
|
||||
return Theme.tempWarning;
|
||||
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
@@ -68,7 +68,12 @@ Rectangle {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: (SysMonitorService.cpuUsage || 0).toFixed(0) + "%"
|
||||
text: {
|
||||
if (SysMonitorService.cpuUsage === undefined || SysMonitorService.cpuUsage === null || SysMonitorService.cpuUsage === 0) {
|
||||
return "--%";
|
||||
}
|
||||
return SysMonitorService.cpuUsage.toFixed(0) + "%";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
|
||||
91
Modules/TopBar/CpuTemperature.qml
Normal file
91
Modules/TopBar/CpuTemperature.qml
Normal file
@@ -0,0 +1,91 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = cpuTempArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||
}
|
||||
Component.onCompleted: {
|
||||
SysMonitorService.addRef();
|
||||
}
|
||||
Component.onDestruction: {
|
||||
SysMonitorService.removeRef();
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: cpuTempArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
||||
var globalPos = mapToGlobal(0, 0);
|
||||
var currentScreen = parentScreen || Screen;
|
||||
var screenX = currentScreen.x || 0;
|
||||
var relativeX = globalPos.x - screenX;
|
||||
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
|
||||
}
|
||||
SysMonitorService.setSortBy("cpu");
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList();
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "memory"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (SysMonitorService.cpuTemperature > 85)
|
||||
return Theme.tempDanger;
|
||||
|
||||
if (SysMonitorService.cpuTemperature > 69)
|
||||
return Theme.tempWarning;
|
||||
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (SysMonitorService.cpuTemperature === undefined || SysMonitorService.cpuTemperature === null || SysMonitorService.cpuTemperature < 0) {
|
||||
return "--°";
|
||||
}
|
||||
return Math.round(SysMonitorService.cpuTemperature) + "°";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
111
Modules/TopBar/GpuTemperature.qml
Normal file
111
Modules/TopBar/GpuTemperature.qml
Normal file
@@ -0,0 +1,111 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property bool showPercentage: true
|
||||
property bool showIcon: true
|
||||
property var toggleProcessList
|
||||
property string section: "right"
|
||||
property var popupTarget: null
|
||||
property var parentScreen: null
|
||||
property var widgetData: null
|
||||
property int selectedGpuIndex: (widgetData && widgetData.selectedGpuIndex !== undefined) ? widgetData.selectedGpuIndex : 0
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onWidgetDataChanged() {
|
||||
// Force property re-evaluation by triggering change detection
|
||||
root.selectedGpuIndex = Qt.binding(() => {
|
||||
return (root.widgetData && root.widgetData.selectedGpuIndex !== undefined) ? root.widgetData.selectedGpuIndex : 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
width: 55
|
||||
height: 30
|
||||
radius: Theme.cornerRadius
|
||||
color: {
|
||||
const baseColor = gpuArea.containsMouse ? Theme.primaryPressed : Theme.secondaryHover;
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency);
|
||||
}
|
||||
Component.onCompleted: {
|
||||
SysMonitorService.addRef();
|
||||
}
|
||||
Component.onDestruction: {
|
||||
SysMonitorService.removeRef();
|
||||
}
|
||||
|
||||
property real displayTemp: {
|
||||
if (!SysMonitorService.availableGpus || SysMonitorService.availableGpus.length === 0) return 0;
|
||||
if (selectedGpuIndex >= 0 && selectedGpuIndex < SysMonitorService.availableGpus.length) {
|
||||
return SysMonitorService.availableGpus[selectedGpuIndex].temperature || 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: gpuArea
|
||||
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (popupTarget && popupTarget.setTriggerPosition) {
|
||||
var globalPos = mapToGlobal(0, 0);
|
||||
var currentScreen = parentScreen || Screen;
|
||||
var screenX = currentScreen.x || 0;
|
||||
var relativeX = globalPos.x - screenX;
|
||||
popupTarget.setTriggerPosition(relativeX, Theme.barHeight + Theme.spacingXS, width, section, currentScreen);
|
||||
}
|
||||
SysMonitorService.setSortBy("cpu");
|
||||
if (root.toggleProcessList)
|
||||
root.toggleProcessList();
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
DankIcon {
|
||||
name: "auto_awesome_mosaic"
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (root.displayTemp > 80)
|
||||
return Theme.tempDanger;
|
||||
|
||||
if (root.displayTemp > 65)
|
||||
return Theme.tempWarning;
|
||||
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
if (root.displayTemp === undefined || root.displayTemp === null || root.displayTemp === 0) {
|
||||
return "--°";
|
||||
}
|
||||
return Math.round(root.displayTemp) + "°";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,10 +57,10 @@ Rectangle {
|
||||
size: Theme.iconSize - 8
|
||||
color: {
|
||||
if (SysMonitorService.memoryUsage > 90)
|
||||
return Theme.error;
|
||||
return Theme.tempDanger;
|
||||
|
||||
if (SysMonitorService.memoryUsage > 75)
|
||||
return Theme.warning;
|
||||
return Theme.tempWarning;
|
||||
|
||||
return Theme.surfaceText;
|
||||
}
|
||||
@@ -68,7 +68,12 @@ Rectangle {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: (SysMonitorService.memoryUsage || 0).toFixed(0) + "%"
|
||||
text: {
|
||||
if (SysMonitorService.memoryUsage === undefined || SysMonitorService.memoryUsage === null || SysMonitorService.memoryUsage === 0) {
|
||||
return "--%";
|
||||
}
|
||||
return SysMonitorService.memoryUsage.toFixed(0) + "%";
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
|
||||
@@ -180,7 +180,13 @@ PanelWindow {
|
||||
return true;
|
||||
case "clipboard":
|
||||
return true;
|
||||
case "systemResources":
|
||||
case "cpuUsage":
|
||||
return true;
|
||||
case "memUsage":
|
||||
return true;
|
||||
case "cpuTemp":
|
||||
return true;
|
||||
case "gpuTemp":
|
||||
return true;
|
||||
case "notificationButton":
|
||||
return true;
|
||||
@@ -217,8 +223,14 @@ PanelWindow {
|
||||
return privacyIndicatorComponent;
|
||||
case "clipboard":
|
||||
return clipboardComponent;
|
||||
case "systemResources":
|
||||
return systemResourcesComponent;
|
||||
case "cpuUsage":
|
||||
return cpuUsageComponent;
|
||||
case "memUsage":
|
||||
return memUsageComponent;
|
||||
case "cpuTemp":
|
||||
return cpuTempComponent;
|
||||
case "gpuTemp":
|
||||
return gpuTempComponent;
|
||||
case "notificationButton":
|
||||
return notificationButtonComponent;
|
||||
case "battery":
|
||||
@@ -606,39 +618,78 @@ PanelWindow {
|
||||
}
|
||||
|
||||
Component {
|
||||
id: systemResourcesComponent
|
||||
id: cpuUsageComponent
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
CpuMonitor {
|
||||
section: {
|
||||
if (parent && parent.parent && parent.parent.parent === leftSection) return "left";
|
||||
if (parent && parent.parent && parent.parent.parent === rightSection) return "right";
|
||||
if (parent && parent.parent && parent.parent.parent === centerSection) return "center";
|
||||
return "right";
|
||||
}
|
||||
popupTarget: processListPopout
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
return processListPopout.toggle();
|
||||
}
|
||||
CpuMonitor {
|
||||
section: {
|
||||
if (parent && parent.parent === leftSection) return "left";
|
||||
if (parent && parent.parent === rightSection) return "right";
|
||||
if (parent && parent.parent === centerSection) return "center";
|
||||
return "right";
|
||||
}
|
||||
|
||||
RamMonitor {
|
||||
section: {
|
||||
if (parent && parent.parent && parent.parent.parent === leftSection) return "left";
|
||||
if (parent && parent.parent && parent.parent.parent === rightSection) return "right";
|
||||
if (parent && parent.parent && parent.parent.parent === centerSection) return "center";
|
||||
return "right";
|
||||
}
|
||||
popupTarget: processListPopout
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
return processListPopout.toggle();
|
||||
}
|
||||
popupTarget: processListPopout
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
return processListPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: memUsageComponent
|
||||
|
||||
RamMonitor {
|
||||
section: {
|
||||
if (parent && parent.parent === leftSection) return "left";
|
||||
if (parent && parent.parent === rightSection) return "right";
|
||||
if (parent && parent.parent === centerSection) return "center";
|
||||
return "right";
|
||||
}
|
||||
popupTarget: processListPopout
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
return processListPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cpuTempComponent
|
||||
|
||||
CpuTemperature {
|
||||
section: {
|
||||
if (parent && parent.parent === leftSection) return "left";
|
||||
if (parent && parent.parent === rightSection) return "right";
|
||||
if (parent && parent.parent === centerSection) return "center";
|
||||
return "right";
|
||||
}
|
||||
popupTarget: processListPopout
|
||||
parentScreen: root.screen
|
||||
toggleProcessList: () => {
|
||||
return processListPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: gpuTempComponent
|
||||
|
||||
GpuTemperature {
|
||||
section: {
|
||||
if (parent && parent.parent === leftSection) return "left";
|
||||
if (parent && parent.parent === rightSection) return "right";
|
||||
if (parent && parent.parent === centerSection) return "center";
|
||||
return "right";
|
||||
}
|
||||
popupTarget: processListPopout
|
||||
parentScreen: root.screen
|
||||
widgetData: parent.widgetData
|
||||
toggleProcessList: () => {
|
||||
return processListPopout.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,13 @@ Rectangle {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°" + (SettingsData.useFahrenheit ? "F" : "C")
|
||||
text: {
|
||||
var temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
|
||||
if (temp === undefined || temp === null || temp === 0) {
|
||||
return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
|
||||
}
|
||||
return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
pragma Singleton
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property bool isIdle: false
|
||||
property int idleThresholdSeconds: 300 // 5 minutes
|
||||
property int checkInterval: 30000 // Check every 30 seconds
|
||||
|
||||
signal idleChanged(bool idle)
|
||||
|
||||
function checkIdleState() {
|
||||
if (idleChecker.running) return
|
||||
idleChecker.running = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: idleTimer
|
||||
interval: root.checkInterval
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: root.checkIdleState()
|
||||
}
|
||||
|
||||
Process {
|
||||
id: idleChecker
|
||||
command: ["bash", "-c", "if command -v xprintidle >/dev/null 2>&1; then echo $(( $(xprintidle) / 1000 )); elif command -v qdbus >/dev/null 2>&1; then qdbus org.freedesktop.ScreenSaver /org/freedesktop/ScreenSaver GetSessionIdleTime 2>/dev/null || echo 0; else echo 0; fi"]
|
||||
running: false
|
||||
|
||||
stdout: SplitParser {
|
||||
splitMarker: "\n"
|
||||
onRead: (data) => {
|
||||
const idleSeconds = parseInt(data.trim()) || 0
|
||||
const wasIdle = root.isIdle
|
||||
root.isIdle = idleSeconds >= root.idleThresholdSeconds
|
||||
|
||||
if (wasIdle !== root.isIdle) {
|
||||
console.log("IdleService: System idle state changed to:", root.isIdle ? "idle" : "active", "(" + idleSeconds + "s)")
|
||||
root.idleChanged(root.isIdle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onExited: (exitCode) => {
|
||||
if (exitCode !== 0) {
|
||||
console.warn("IdleService: Failed to check idle state, exit code:", exitCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log("IdleService: Initialized with", root.idleThresholdSeconds + "s threshold")
|
||||
checkIdleState()
|
||||
}
|
||||
}
|
||||
@@ -8,21 +8,23 @@ import qs.Services
|
||||
Singleton {
|
||||
id: root
|
||||
property int refCount: 0
|
||||
property int updateInterval: refCount > 0 ? 2000 : 30000
|
||||
property int updateInterval: refCount > 0 ? 3000 : 30000
|
||||
property int maxProcesses: 100
|
||||
property bool isUpdating: false
|
||||
|
||||
property var processes: []
|
||||
property string sortBy: "cpu"
|
||||
property bool sortDescending: true
|
||||
|
||||
property var lastProcTicks: ({})
|
||||
property real lastTotalJiffies: -1
|
||||
|
||||
property real cpuUsage: 0
|
||||
property real totalCpuUsage: 0
|
||||
property int cpuCores: 1
|
||||
property int cpuCount: 1
|
||||
property string cpuModel: ""
|
||||
property real cpuFrequency: 0
|
||||
property real cpuTemperature: 0
|
||||
property real cpuTemperature: -1
|
||||
property var perCoreCpuUsage: []
|
||||
|
||||
property var lastCpuStats: null
|
||||
@@ -69,6 +71,7 @@ Singleton {
|
||||
property string bootTime: ""
|
||||
property string motherboard: ""
|
||||
property string biosVersion: ""
|
||||
property var availableGpus: []
|
||||
|
||||
function addRef() {
|
||||
refCount++;
|
||||
@@ -277,19 +280,43 @@ Singleton {
|
||||
}
|
||||
lastDiskStats = { "read": totalRead, "write": totalWrite };
|
||||
}
|
||||
|
||||
|
||||
let totalDiff = 0;
|
||||
if (data.cpu && data.cpu.total && data.cpu.total.length >= 4) {
|
||||
const currentTotal = data.cpu.total.reduce((s,v)=>s+v, 0);
|
||||
if (lastTotalJiffies > 0)
|
||||
totalDiff = currentTotal - lastTotalJiffies;
|
||||
lastTotalJiffies = currentTotal;
|
||||
}
|
||||
|
||||
if (data.processes) {
|
||||
const newProcesses = [];
|
||||
for (const proc of data.processes) {
|
||||
const pid = proc.pid;
|
||||
const pticks = Number(proc.pticks) || 0;
|
||||
const prev = lastProcTicks[pid] ?? null;
|
||||
let cpuShare = 0;
|
||||
|
||||
if (prev !== null && totalDiff > 0) {
|
||||
// Per share all CPUs (matches gnome system monitor)
|
||||
cpuShare = 100 * Math.max(0, pticks - prev) / totalDiff;
|
||||
|
||||
// per-share per-core
|
||||
//cpuShare = 100 * cpuCores * Math.max(0, pticks - prev) / totalDiff;
|
||||
}
|
||||
|
||||
lastProcTicks[pid] = pticks; // update cache
|
||||
|
||||
newProcesses.push({
|
||||
"pid": proc.pid,
|
||||
"pid": pid,
|
||||
"ppid": proc.ppid,
|
||||
"cpu": proc.cpu,
|
||||
"cpu": cpuShare,
|
||||
"memoryPercent": proc.pssPercent ?? proc.memoryPercent,
|
||||
"memoryKB": proc.pssKB ?? proc.memoryKB,
|
||||
"command": proc.command,
|
||||
"fullCommand": proc.fullCommand,
|
||||
"displayName": 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
|
||||
});
|
||||
}
|
||||
processes = newProcesses;
|
||||
@@ -313,6 +340,10 @@ Singleton {
|
||||
diskMounts = data.diskmounts;
|
||||
}
|
||||
|
||||
if (data.gpus) {
|
||||
availableGpus = data.gpus;
|
||||
}
|
||||
|
||||
addToHistory(cpuHistory, cpuUsage);
|
||||
addToHistory(memoryHistory, memoryUsage);
|
||||
|
||||
@@ -358,32 +389,16 @@ Singleton {
|
||||
return (mem / (1024 * 1024)).toFixed(1) + " GB";
|
||||
}
|
||||
|
||||
function getCpuTempCentigrade() {
|
||||
cpuTempProcess.running = true;
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: root.updateInterval
|
||||
running: root.refCount > 0 && !IdleService.isIdle
|
||||
running: root.refCount > 0
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: root.updateAllStats()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: IdleService
|
||||
function onIdleChanged(idle) {
|
||||
if (idle) {
|
||||
console.log("SysMonitorService: System idle, pausing monitoring")
|
||||
} else {
|
||||
console.log("SysMonitorService: System active, resuming monitoring")
|
||||
if (root.refCount > 0) {
|
||||
root.updateAllStats()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string scriptBody: `set -Eeuo pipefail
|
||||
trap 'echo "ERR at line $LINENO: $BASH_COMMAND (exit $?)" >&2' ERR
|
||||
@@ -410,28 +425,53 @@ printf '"memory":{"total":%d,"free":%d,"available":%d,"buffers":%d,"cached":%d,"
|
||||
|
||||
# Get pss per pid
|
||||
get_pss_kb() {
|
||||
local pid="$1"
|
||||
if [ -r "/proc/$pid/smaps_rollup" ]; then
|
||||
awk '/^Pss:/{print $2; exit}' "/proc/$pid/smaps_rollup"
|
||||
elif [ -r "/proc/$pid/smaps" ]; then
|
||||
awk '/^Pss:/{t+=$2} END{print t+0}' "/proc/$pid/smaps"
|
||||
else
|
||||
echo 0
|
||||
# Read PSS with zero external processes.
|
||||
# 1) Prefer smaps_rollup (fast, single file)
|
||||
# 2) Fallback to summing PSS in smaps
|
||||
# Return 0 if unavailable.
|
||||
local pid="$1" f total v k _
|
||||
f="/proc/$pid/smaps_rollup"
|
||||
if [ -r "$f" ]; then
|
||||
# smaps_rollup has one Pss: line — read it directly
|
||||
while read -r k v _; do
|
||||
if [ "$k" = "Pss:" ]; then
|
||||
printf '%s\n' "\${v:-0}"
|
||||
return
|
||||
fi
|
||||
done < "$f"
|
||||
printf '0\n'
|
||||
return
|
||||
fi
|
||||
f="/proc/$pid/smaps"
|
||||
if [ -r "$f" ]; then
|
||||
total=0
|
||||
while read -r k v _; do
|
||||
[ "$k" = "Pss:" ] && total=$(( total + (v:-0) ))
|
||||
done < "$f"
|
||||
printf '%s\n' "$total"
|
||||
return
|
||||
fi
|
||||
printf '0\n'
|
||||
}
|
||||
|
||||
cpu_count=$(nproc)
|
||||
cpu_model=$(grep -m1 'model name' /proc/cpuinfo | cut -d: -f2- | sed 's/^ *//' | json_escape || echo 'Unknown')
|
||||
cpu_freq=$(awk -F: '/cpu MHz/{gsub(/ /,"",$2);print $2;exit}' /proc/cpuinfo || echo 0)
|
||||
cpu_temp=$(if [ -r /sys/class/thermal/thermal_zone0/temp ]; then
|
||||
awk '{printf "%.1f",$1/1000}' /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo 0
|
||||
else echo 0; fi)
|
||||
cpu_temp=$(grep -l 'coretemp\\|k10temp\\|k8temp\\|cpu_thermal\\|soc_thermal' /sys/class/hwmon/hwmon*/name 2>/dev/null | sed 's/name$/temp1_input/' | xargs cat 2>/dev/null | awk '{print $1/1000}' | head -1 || echo 0)
|
||||
|
||||
printf '"cpu":{"count":%d,"model":"%s","frequency":%s,"temperature":%s,' \\
|
||||
"$cpu_count" "$cpu_model" "$cpu_freq" "$cpu_temp"
|
||||
|
||||
printf '"total":'
|
||||
awk 'NR==1 {printf "[%d,%d,%d,%d,%d,%d,%d,%d]", $2,$3,$4,$5,$6,$7,$8,$9; exit}' /proc/stat
|
||||
awk 'NR==1 {
|
||||
printf "[";
|
||||
for(i=2; i<=NF; i++) {
|
||||
if(i>2) printf ",";
|
||||
printf "%d", $i;
|
||||
}
|
||||
printf "]";
|
||||
exit
|
||||
}' /proc/stat
|
||||
|
||||
printf ',"cores":['
|
||||
cpu_cores=$(nproc)
|
||||
@@ -492,23 +532,19 @@ pfirst=1
|
||||
while IFS=' ' read -r pid ppid cpu pmem_rss rss_kib comm rest; do
|
||||
[ -z "$pid" ] && continue
|
||||
|
||||
# Optionally skip kernel threads / empty RSS lines (uncomment to filter)
|
||||
# [ "$rss_kib" -eq 0 ] && continue
|
||||
# Per-process CPU ticks (utime+stime)
|
||||
pticks=$(awk '{print $14+$15}' "/proc/$pid/stat" 2>/dev/null || echo 0)
|
||||
|
||||
pss_kib=$(get_pss_kb "$pid" 2>/dev/null || true)
|
||||
# Force numeric default if empty or non-numeric
|
||||
if [ "\${rss_kib:-0}" -eq 0 ]; then pss_kib=0; else pss_kib=$(get_pss_kb "$pid"); fi
|
||||
case "$pss_kib" in (''|*[!0-9]*) pss_kib=0 ;; esac
|
||||
|
||||
# PSS-based percent (locale-safe)
|
||||
pss_pct=$(LC_ALL=C awk -v p="$pss_kib" -v t="$MT" 'BEGIN{if(t>0) printf "%.2f", (100*p)/t; else printf "0.00"}')
|
||||
|
||||
# Build full command; escape both fields
|
||||
cmd=$(printf "%s %s" "$comm" "\${rest:-}" | json_escape)
|
||||
comm_esc=$(printf "%s" "$comm" | json_escape)
|
||||
|
||||
[ "$pfirst" -eq 1 ] || printf ","
|
||||
printf '{"pid":%s,"ppid":%s,"cpu":%s,"memoryPercent":%s,"memoryKB":%s,"pssKB":%s,"pssPercent":%s,"command":"%s","fullCommand":"%s"}' \
|
||||
"$pid" "$ppid" "$cpu" "$pss_pct" "$rss_kib" "$pss_kib" "$pss_pct" "$comm_esc" "$cmd"
|
||||
[ $pfirst -eq 1 ] || printf ","
|
||||
printf '{"pid":%s,"ppid":%s,"cpu":%s,"pticks":%s,"memoryPercent":%s,"memoryKB":%s,"pssKB":%s,"pssPercent":%s,"command":"%s","fullCommand":"%s"}' \
|
||||
"$pid" "$ppid" "$cpu" "$pticks" "$pss_pct" "$rss_kib" "$pss_kib" "$pss_pct" "$comm_esc" "$cmd"
|
||||
pfirst=0
|
||||
done < "$tmp_ps"
|
||||
rm -f "$tmp_ps"
|
||||
@@ -526,8 +562,8 @@ distro=$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2- | tr -d '"'
|
||||
host_name=$(hostname | json_escape)
|
||||
arch_name=$(uname -m)
|
||||
load_avg=$(cut -d' ' -f1-3 /proc/loadavg)
|
||||
proc_count=$(( $(ps aux | wc -l) - 1 ))
|
||||
thread_count=$(ps -eL | wc -l)
|
||||
proc_count=$(ls -Ud /proc/[0-9]* 2>/dev/null | wc -l)
|
||||
thread_count=$(ls -Ud /proc/[0-9]*/task/[0-9]* 2>/dev/null | wc -l)
|
||||
boot_time=$(who -b 2>/dev/null | awk '{print $3, $4}' | json_escape || echo 'Unknown')
|
||||
|
||||
printf '"system":{"kernel":"%s","distro":"%s","hostname":"%s","arch":"%s","loadavg":"%s","processes":%d,"threads":%d,"boottime":"%s","motherboard":"%s %s","bios":"%s %s"},' \\
|
||||
@@ -552,6 +588,78 @@ while IFS= read -r line; do
|
||||
mfirst=0
|
||||
done < "$tmp_mounts"
|
||||
rm -f "$tmp_mounts"
|
||||
printf ']',
|
||||
|
||||
printf '"gpus":['
|
||||
gfirst=1
|
||||
tmp_gpu=$(mktemp)
|
||||
|
||||
# Gather cards via DRM (much cheaper than lspci each tick)
|
||||
for card in /sys/class/drm/card*; do
|
||||
[ -e "$card/device/driver" ] || continue
|
||||
|
||||
drv=$(basename "$(readlink -f "$card/device/driver")") # e.g. nvidia, amdgpu, i915
|
||||
drv=\${drv##*/}
|
||||
|
||||
# Determine PCI secondary bus to help identify integrated vs discrete
|
||||
pci_path=$(readlink -f "$card/device") # .../0000:01:00.0
|
||||
func=\${pci_path##*/} # 0000:01:00.0
|
||||
sec=\${func#*:}; sec=\${sec%%:*} # "01" from 0000:01:00.0
|
||||
|
||||
# Priority: higher = more likely dedicated
|
||||
prio=0
|
||||
case "$drv" in
|
||||
nvidia) prio=3 ;; # dGPU
|
||||
amdgpu|radeon)
|
||||
if [ "$sec" = "00" ]; then prio=1; else prio=2; fi # APU often on bus 00
|
||||
;;
|
||||
i915) prio=0 ;; # iGPU
|
||||
*) prio=0 ;;
|
||||
esac
|
||||
|
||||
# Temperature via per-device hwmon if available
|
||||
hw=""; temp="0"
|
||||
for h in "$card/device"/hwmon/hwmon*; do
|
||||
[ -e "$h/temp1_input" ] || continue
|
||||
hw=$(basename "$h")
|
||||
temp=$(awk '{printf "%.1f",$1/1000}' "$h/temp1_input" 2>/dev/null || echo "0")
|
||||
break
|
||||
done
|
||||
|
||||
# NVIDIA fallback: use nvidia-smi (first GPU) if temp still 0
|
||||
if [ "$drv" = "nvidia" ] && command -v nvidia-smi >/dev/null 2>&1; then
|
||||
t=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits 2>/dev/null | head -1)
|
||||
[ -n "$t" ] && { temp="$t"; hw="\${hw:-nvidia}"; }
|
||||
fi
|
||||
|
||||
printf '%s|%s|%s|%s\n' "$prio" "$drv" "\${hw:-unknown}" "\${temp:-0}" >> "$tmp_gpu"
|
||||
done
|
||||
|
||||
# Fallback if no DRM cards found (keep drivers but still sort)
|
||||
if [ ! -s "$tmp_gpu" ]; then
|
||||
for drv in nvidia amdgpu radeon i915; do
|
||||
command -v "$drv" >/dev/null 2>&1 || true
|
||||
prio=0; [ "$drv" = "nvidia" ] && prio=3
|
||||
[ "$drv" = "amdgpu" ] && prio=2
|
||||
[ "$drv" = "radeon" ] && prio=2
|
||||
[ "$drv" = "i915" ] && prio=0
|
||||
temp="0"; hw="$drv"
|
||||
if [ "$drv" = "nvidia" ] && command -v nvidia-smi >/dev/null 2>&1; then
|
||||
t=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits 2>/dev/null | head -1)
|
||||
[ -n "$t" ] && temp="$t"
|
||||
fi
|
||||
printf '%s|%s|%s|%s\n' "$prio" "$drv" "$hw" "$temp" >> "$tmp_gpu"
|
||||
done
|
||||
fi
|
||||
|
||||
# Sort by priority (desc), then driver name for stability, and emit SAME JSON shape
|
||||
while IFS='|' read -r pr drv hw temp; do
|
||||
[ $gfirst -eq 1 ] || printf ","
|
||||
printf '{"driver":"%s","hwmon":"%s","temperature":%s}' "$drv" "$hw" "$temp"
|
||||
gfirst=0
|
||||
done < <(sort -t'|' -k1,1nr -k2,2 "$tmp_gpu")
|
||||
|
||||
rm -f "$tmp_gpu"
|
||||
printf ']'
|
||||
|
||||
printf "}\\n"`
|
||||
@@ -559,9 +667,9 @@ printf "}\\n"`
|
||||
Process {
|
||||
id: unifiedStatsProcess
|
||||
command: [
|
||||
"bash", "-c",
|
||||
"bash -s \"$1\" \"$2\" <<'QS_EOF'\\n" + root.scriptBody + "\\nQS_EOF\\n",
|
||||
"qsmon", root.sortBy, root.maxProcesses
|
||||
"bash", "-c",
|
||||
"bash -s \"$1\" \"$2\" <<'QS_EOF'\n" + root.scriptBody + "\nQS_EOF\n",
|
||||
root.sortBy, String(root.maxProcesses)
|
||||
]
|
||||
running: false
|
||||
onExited: (exitCode) => {
|
||||
@@ -594,17 +702,5 @@ printf "}\\n"`
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: cpuTempProcess
|
||||
command: ["bash", "-c", "grep -l 'coretemp\\|k10temp\\|k8temp\\|cpu_thermal\\|soc_thermal' /sys/class/hwmon/hwmon*/name | sed 's/name$/temp1_input/' | xargs cat | awk '{print $1/1000}'"]
|
||||
running: false
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
const temp = parseFloat(text.trim());
|
||||
if (!isNaN(temp)) {
|
||||
cpuTemperature = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,7 +246,7 @@ Singleton {
|
||||
Timer {
|
||||
id: updateTimer
|
||||
interval: root.updateInterval
|
||||
running: root.refCount > 0 && !IdleService.isIdle && SettingsData.weatherEnabled
|
||||
running: root.refCount > 0 && SettingsData.weatherEnabled
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
@@ -254,21 +254,6 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: IdleService
|
||||
function onIdleChanged(idle) {
|
||||
if (idle) {
|
||||
console.log("WeatherService: System idle, pausing weather updates")
|
||||
} else {
|
||||
console.log("WeatherService: System active, resuming weather updates")
|
||||
if (root.refCount > 0 && !root.weather.available && SettingsData.weatherEnabled) {
|
||||
// Trigger immediate update when coming back from idle if no data and weather enabled
|
||||
root.fetchWeather()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: retryTimer
|
||||
interval: root.retryDelay
|
||||
|
||||
@@ -22,7 +22,7 @@ Rectangle {
|
||||
width: parent.width
|
||||
height: 60
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceHover
|
||||
color: "transparent"
|
||||
Component.onCompleted: {
|
||||
forceRecreateTimer.start();
|
||||
}
|
||||
@@ -272,6 +272,8 @@ Rectangle {
|
||||
DankListView {
|
||||
id: listView
|
||||
|
||||
property var popupRef: dropdownMenu
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - (root.enableFuzzySearch ? searchContainer.height + Theme.spacingXS : 0)
|
||||
clip: true
|
||||
@@ -339,7 +341,7 @@ Rectangle {
|
||||
onClicked: {
|
||||
root.currentValue = modelData;
|
||||
root.valueChanged(modelData);
|
||||
close();
|
||||
dropdownMenu.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import qs.Common
|
||||
Flickable {
|
||||
id: flickable
|
||||
|
||||
property real mouseWheelSpeed: 12
|
||||
property real mouseWheelSpeed: 60
|
||||
property real momentumVelocity: 0
|
||||
property bool isMomentumActive: false
|
||||
property real friction: 0.95
|
||||
|
||||
@@ -22,7 +22,7 @@ GridView {
|
||||
id: wheelHandler
|
||||
|
||||
// Tunable parameters for responsive scrolling
|
||||
property real mouseWheelSpeed: 20
|
||||
property real mouseWheelSpeed: 60
|
||||
// Higher = faster mouse wheel
|
||||
property real touchpadSpeed: 1.8
|
||||
// Touchpad sensitivity
|
||||
|
||||
@@ -4,7 +4,7 @@ import QtQuick.Controls
|
||||
ListView {
|
||||
id: listView
|
||||
|
||||
property real mouseWheelSpeed: 12
|
||||
property real mouseWheelSpeed: 60
|
||||
|
||||
// Simple position preservation
|
||||
property real savedY: 0
|
||||
|
||||
Reference in New Issue
Block a user