diff --git a/debug_graphs.txt b/debug_graphs.txt new file mode 100644 index 0000000..0880b78 --- /dev/null +++ b/debug_graphs.txt @@ -0,0 +1,17 @@ +# CPU +[{"_v":1,"type":"cpu","colors":["highlightColor","textColor","textColor"],"sensorsType":["usage","classic",true],"clockAgregator":"average","eCoresCount":0,"thresholds":[85,105]}] + +# Memory +[{"_v":1,"type":"memory","colors":["highlightColor","negativeTextColor"],"sensorsType":["physical","swap"],"thresholds":[70,90]}] + +# GPU +[{"_v":1,"type":"gpu","colors":["highlightColor","positiveTextColor","textColor"],"sensorsType":["memory",true],"thresholds":[70,90],"gpuIndex":"gpu1"}] + +# Network +[{"_v":1,"type":"network","colors":["highlightColor","positiveTextColor"],"sensorsType":["kibibyte"],"uplimits":[100000,100000],"ignoredInterfaces":[]}] + +# Disks +[{"_v":1,"type":"disks","colors":["highlightColor","positiveTextColor"],"uplimits":[200000,200000]}] + +# Full +[{"_v":1,"type":"cpu","colors":["highlightColor","textColor","textColor"],"sensorsType":["usage","classic",true],"clockAgregator":"average","eCoresCount":0,"thresholds":[85,105]},{"_v":1,"type":"memory","colors":["highlightColor","negativeTextColor"],"sensorsType":["physical","swap"],"thresholds":[70,90]},{"_v":1,"type":"gpu","colors":["highlightColor","positiveTextColor","textColor"],"sensorsType":["memory",true],"thresholds":[70,90],"gpuIndex":"gpu1"},{"_v":1,"type":"network","colors":["highlightColor","positiveTextColor"],"sensorsType":["kibibyte"],"uplimits":[100000,100000],"ignoredInterfaces":[]},{"_v":1,"type":"disks","colors":["highlightColor","positiveTextColor"],"uplimits":[200000,200000]}] diff --git a/package/contents/config/config.qml b/package/contents/config/config.qml index 0ae10ca..deed233 100644 --- a/package/contents/config/config.qml +++ b/package/contents/config/config.qml @@ -3,18 +3,19 @@ import org.kde.plasma.configuration ConfigModel { ConfigCategory { - name: i18nc("Config header", "General") - icon: 'preferences-desktop-plasma' - source: 'config/ConfigGeneral.qml' - } - ConfigCategory { - name: i18nc("Config header", "Data") - icon: 'preferences-desktop' - source: 'config/ConfigData.qml' + name: i18nc("Config header", "Graphs") + icon: 'office-chart-line-stacked' + source: 'config/ConfigGraph.qml' + includeMargins: false } ConfigCategory { name: i18nc("Config header", "Appearance") icon: 'preferences-desktop-color' source: 'config/ConfigAppearance.qml' } + ConfigCategory { + name: i18nc("Config header", "Misc") + icon: 'preferences-system-other' + source: 'config/ConfigMisc.qml' + } } diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index ca4e41b..4f7ac44 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -9,82 +9,9 @@ 1.0 - - - - - - - - usage - - - - - - - - classic - - - - - - - - average - - - false - - - - - - - - - - - physical - - - - - - - - - swap - - - - - - - - - - none - - - - false - - - - - - - - memory - - - false - - - - false + + + [{"_v":1,"type":"cpu","colors":["highlightColor","textColor","textColor"],"sensorsType":["usage","classic",false],"clockAgregator":"average","eCoresCount":0,"thresholds":[85,105]},{"_v":1,"type":"memory","colors":["highlightColor","negativeTextColor"],"sensorsType":["physical","swap"],"thresholds":[70,90]}] @@ -92,51 +19,6 @@ - - - 0 - - - - - - 100000.0 - - - 100000.0 - - - - 200000.0 - - - 200000.0 - - - - gpu0 - - - - 85.0 - - - 105.0 - - - 70 - - - 90 - - - 75 - - - 85 - - - false @@ -173,48 +55,6 @@ top-right - - cpu,memory,gpu,disks,network - - - - highlightColor - - - textColor - - - - highlightColor - - - negativeTextColor - - - - highlightColor - - - positiveTextColor - - - - highlightColor - - - positiveTextColor - - - textColor - - - - highlightColor - - - positiveTextColor - - neutralTextColor diff --git a/package/contents/ui/components/functions.mjs b/package/contents/ui/components/functions.mjs index 15bb42f..c939a62 100644 --- a/package/contents/ui/components/functions.mjs +++ b/package/contents/ui/components/functions.mjs @@ -108,7 +108,9 @@ export function formatByteValue(value, dialect, precision = 1) { * @returns The color color */ export function resolveColor(color) { - if (color.startsWith("#")) { + if (!color) { + return undefined; + } else if (color.startsWith("#")) { return color; } return _kirigamiTheme[color] || _kirigamiTheme.textColor; diff --git a/package/contents/ui/components/graph/CpuGraph.qml b/package/contents/ui/components/graph/CpuGraph.qml index 2e3060f..796aa51 100644 --- a/package/contents/ui/components/graph/CpuGraph.qml +++ b/package/contents/ui/components/graph/CpuGraph.qml @@ -1,64 +1,55 @@ import QtQuick import org.kde.plasma.plasmoid -import org.kde.kirigami as Kirigami import "./base" as RMBaseGraph import "../sensors" as RMSensors -import "../functions.mjs" as Functions RMBaseGraph.SensorGraph { id: root objectName: "CpuGraph" - // Config shrotcut - property bool showClock: Plasmoid.configuration.cpuClockType !== "none" - property bool clockIsEcores: Plasmoid.configuration.cpuClockType === "ecores" - property color temperatureColor: Functions.resolveColor(Plasmoid.configuration.cpuTemperatureColor) + // Settings + property string clockAgregator: "average" // Values: average, minimum, maximum + property int eCoresCount: 0 - // Handle config update - Connections { - target: Plasmoid.configuration - function onCpuUnitChanged() { - _updateSensors(); - } - } + // Config shortcut + property bool showClock: sensorsType[1] !== "none" + property bool clockIsEcores: sensorsType[1] === "ecores" // Graph options // NOTE: "sensorsModel.sensors" is set by "_updateSensors" - chartColor: Functions.resolveColor(Plasmoid.configuration.cpuColor) - chart.yRange { from: 0 to: 100 } // Labels options - thresholds: [undefined, undefined, [Plasmoid.configuration.thresholdWarningCpuTemp, Plasmoid.configuration.thresholdCriticalCpuTemp]] - + thresholdIndex: 2 + realThresholds: thresholds // No change needed, simply map it textContainer { - labelColors: [root.chartColor, undefined, temperatureColor] - valueColors: [undefined, undefined, temperatureColor] + labelColors: [root.colors[0], undefined, root.colors[2]] + valueColors: [undefined, undefined, root.colors[2]] - labels: ["CPU", (showClock ? i18nc("Graph label", "Clock") : ""), (Plasmoid.configuration.showCpuTemperature ? i18nc("Graph label", "Temp.") : "")] + labels: ["CPU", (root.showClock ? i18nc("Graph label", "Clock") : ""), (root.sensorsType[2] ? i18nc("Graph label", "Temp.") : "")] } // CPU frequency handle _formatValue: (index, data) => { if (index === 1) { - return cpuFrequenry.getFormattedValue(clockIsEcores); + return cpuFrequenry.getFormattedValue(root.clockIsEcores); } return _defaultFormatValue(index, data); } RMSensors.CpuFrequency { id: cpuFrequenry - enabled: showClock - agregator: Plasmoid.configuration.cpuClockAgregator - eCoresCount: Plasmoid.configuration.cpuECoresCount + enabled: root.showClock + agregator: root.clockAgregator + eCoresCount: root.eCoresCount - onReady: _updateSensors() + onReady: root._updateSensors() } function _updateSensors() { - sensorsModel.sensors = ["cpu/all/" + Plasmoid.configuration.cpuUnit, "cpu/cpu0/frequency", "cpu/cpu0/temperature"]; + sensorsModel.sensors = ["cpu/all/" + sensorsType[0], "cpu/cpu0/frequency", "cpu/cpu0/temperature"]; } } diff --git a/package/contents/ui/components/graph/DisksGraph.qml b/package/contents/ui/components/graph/DisksGraph.qml index 48b68ab..90effa2 100644 --- a/package/contents/ui/components/graph/DisksGraph.qml +++ b/package/contents/ui/components/graph/DisksGraph.qml @@ -7,32 +7,17 @@ RMBaseGraph.TwoSensorsGraph { id: root objectName: "DisksGraph" + // Apply dialect to uplimits readonly property var diskIoDialect: Functions.getNetworkDialectInfo("kibibyte", i18nc) - - Connections { - target: Plasmoid.configuration - function onDiskReadTotalChanged() { - _updateUplimits(); - } - function onDiskWriteTotalChanged() { - _updateUplimits(); - } - } Component.onCompleted: { - _updateUplimits(); + realUplimits = [uplimits[0] * diskIoDialect.multiplier, uplimits[1] * diskIoDialect.multiplier]; } // Labels textContainer { - labelColors: root.colors labels: [i18nc("Graph label", "Read"), i18nc("Graph label", "Write"), ""] } // Graph options sensorsModel.sensors: ["disk/all/read", "disk/all/write"] - colors: [Functions.resolveColor(Plasmoid.configuration.diskReadColor), Functions.resolveColor(Plasmoid.configuration.diskWriteColor)] - - function _updateUplimits() { - uplimits = [Plasmoid.configuration.diskReadTotal * diskIoDialect.multiplier, Plasmoid.configuration.diskWriteTotal * diskIoDialect.multiplier]; - } } diff --git a/package/contents/ui/components/graph/GpuGraph.qml b/package/contents/ui/components/graph/GpuGraph.qml index e2bd7eb..03ca433 100644 --- a/package/contents/ui/components/graph/GpuGraph.qml +++ b/package/contents/ui/components/graph/GpuGraph.qml @@ -2,38 +2,29 @@ import QtQuick import org.kde.plasma.plasmoid import org.kde.ksysguard.sensors as Sensors import "./base" as RMBaseGraph -import "../functions.mjs" as Functions RMBaseGraph.TwoSensorsGraph { id: root objectName: "GpuGraph" - // Config options - property color temperatureColor: Functions.resolveColor(Plasmoid.configuration.gpuTemperatureColor) - property bool memoryInPercent: Plasmoid.configuration.gpuMemoryUnit.endsWith("-percent") + // Settings + property string gpuIndex: "" // Gpu sensor index (eg: gpu0, gpu1) - // Bind config changes - Connections { - target: Plasmoid.configuration - function onGpuIndexChanged() { - maxQueryModel.enabled = true - } - } + // Config shortcut + property bool memoryInPercent: sensorsType[0].endsWith("-percent") // Labels - thresholds: [undefined, undefined, [Plasmoid.configuration.thresholdWarningGpuTemp, Plasmoid.configuration.thresholdCriticalGpuTemp]] - + thresholdIndex: 2 + realThresholds: thresholds // No change needed, simply map it textContainer { - labelColors: [root.colors[0], root.colors[1], temperatureColor] - valueColors: [undefined, undefined, temperatureColor] + valueColors: [undefined, undefined, root.colors[2]] - labels: ["GPU", (secondChartVisible ? "VRAM" : ""), (Plasmoid.configuration.showGpuTemperature ? i18nc("Graph label", "Temp.") : "")] + labels: ["GPU", (secondChartVisible ? "VRAM" : ""), (sensorsType[1] ? i18nc("Graph label", "Temp.") : "")] } // Graph options // NOTE: "sensorsModel.sensors" set from "maxQueryModel" - colors: [Functions.resolveColor(Plasmoid.configuration.gpuColor), Functions.resolveColor(Plasmoid.configuration.gpuMemoryColor)] - secondChartVisible: Plasmoid.configuration.gpuMemoryUnit !== "none" + secondChartVisible: sensorsType[0] !== "none" // Override methods, for handle memeory in percent _formatValue: (index, data) => { @@ -46,7 +37,7 @@ RMBaseGraph.TwoSensorsGraph { // Initialize limits and threshold Sensors.SensorDataModel { id: maxQueryModel - sensors: ["gpu/" + Plasmoid.configuration.gpuIndex + "/totalVram"] + sensors: [`gpu/${gpuIndex}/totalVram`] enabled: true property int maxMemory: -1 @@ -63,8 +54,7 @@ RMBaseGraph.TwoSensorsGraph { root.uplimits = [100, maxMemory]; // Update sensors - const gpu = Plasmoid.configuration.gpuIndex - root.sensorsModel.sensors = ["gpu/" + gpu + "/usage", "gpu/" + gpu + "/usedVram", "gpu/" + gpu + "/temperature"]; + root.sensorsModel.sensors = [`gpu/${gpuIndex}/usage`, `gpu/${gpuIndex}/usedVram`, `gpu/${gpuIndex}/temperature`]; } } } diff --git a/package/contents/ui/components/graph/MemoryGraph.qml b/package/contents/ui/components/graph/MemoryGraph.qml index 664e621..ddd0536 100644 --- a/package/contents/ui/components/graph/MemoryGraph.qml +++ b/package/contents/ui/components/graph/MemoryGraph.qml @@ -2,42 +2,18 @@ import QtQuick import org.kde.plasma.plasmoid import org.kde.ksysguard.sensors as Sensors import "./base" as RMBaseGraph -import "../functions.mjs" as Functions RMBaseGraph.TwoSensorsGraph { id: root objectName: "MemoryGraph" // Config shrotcut - property bool showSwap: Plasmoid.configuration.memorySecondUnit.startsWith("swap") - property var fieldInPercent: [Plasmoid.configuration.memoryUnit.endsWith("-percent"), Plasmoid.configuration.memorySecondUnit === "swap-percent"] - - // Handle config update and init - Connections { - target: Plasmoid.configuration - function onMemoryUnitChanged() { // Values: usage, system, user - _updateSensorsAndLabels(); - } - function onMemorySecondUnitChanged() { - _updateSensorsAndLabels(); - } - - function onThresholdWarningMemoryChanged() { - _updateThresholds(); - } - function onThresholdCriticalMemoryChanged() { - _updateThresholds(); - } - } - Component.onCompleted: { - _updateThresholds(); - _updateSensorsAndLabels(); - } + property bool showSwap: sensorsType[1].startsWith("swap") + property var fieldInPercent: [sensorsType[0].endsWith("-percent"), sensorsType[1] === "swap-percent"] // Labels textContainer { - labelColors: root.colors - valueColors: [undefined, showSwap ? root.colors[1] : undefined] + valueColors: [undefined, root.showSwap ? root.colors[1] : undefined] labelsVisibleWhenZero: [true, false, true] // NOTE: second label is set by "_updateSensorsAndLabels" @@ -46,7 +22,6 @@ RMBaseGraph.TwoSensorsGraph { // Graph options // NOTE: "sensorsModel.sensors" is set by "_updateSensorsAndLabels" - colors: [Functions.resolveColor(Plasmoid.configuration.memColor), Functions.resolveColor(Plasmoid.configuration.memSecondColor)] secondChartVisible: showSwap && Plasmoid.configuration.historyAmount > 0 // Override methods, for handle memeory in percent @@ -75,27 +50,22 @@ RMBaseGraph.TwoSensorsGraph { // Update graph Y range and sensors if (maxMemory[0] > 0 && maxMemory[1] >= 0) { enabled = false; - root.uplimits = maxMemory; - root._updateThresholds(); + root.realUplimits = maxMemory; + root.realThresholds = [maxMemory[0] * (root.thresholds[0] / 100.0), maxMemory[0] * (root.thresholds[1] / 100.0)]; root._updateSensorsAndLabels(); } } } - function _updateThresholds() { - const thresholdWarningMemory = Plasmoid.configuration.thresholdWarningMemory; - const thresholdCriticalMemory = Plasmoid.configuration.thresholdCriticalMemory; - thresholds[0] = [maxQueryModel.maxMemory[0] * (thresholdWarningMemory / 100.0), maxQueryModel.maxMemory[0] * (thresholdCriticalMemory / 100.0)]; - } function _updateSensorsAndLabels() { - const info = Plasmoid.configuration.memoryUnit.split("-"); + const info = sensorsType[0].split("-"); const oldSecondLabel = textContainer.labels[1]; // Define sensors and second label const type = info[0] === "physical" ? "used" : "application"; const firstSensor = "memory/physical/" + type; let secondSensor; - switch (Plasmoid.configuration.memorySecondUnit) { + switch (sensorsType[1]) { case "memory-percent": secondSensor = "memory/physical/" + type + "Percent"; textContainer.labels[1] = i18nc("Graph label", "Percent."); diff --git a/package/contents/ui/components/graph/NetworkGraph.qml b/package/contents/ui/components/graph/NetworkGraph.qml index d74457e..219cf3c 100644 --- a/package/contents/ui/components/graph/NetworkGraph.qml +++ b/package/contents/ui/components/graph/NetworkGraph.qml @@ -2,38 +2,27 @@ import QtQuick import org.kde.plasma.plasmoid import "./base" as RMBaseGraph import "../" as RMComponents -import "../functions.js" as Functions +import "../functions.mjs" as Functions RMBaseGraph.TwoSensorsGraph { id: root objectName: "NetworkGraph" - property var dialect: Functions.getNetworkDialectInfo(Plasmoid.configuration.networkUnit, i18nc) + // Settings + property var ignoredInterfaces: [] - Connections { - target: Plasmoid.configuration - function onIgnoredNetworkInterfacesChanged() { - _updateSensors(); - } + property var dialect: Functions.getNetworkDialectInfo(sensorsType[0], i18nc) - function onNetworkReceivingTotalChanged() { - _updateUplimits(); - } - function onNetworkSendingTotalChanged() { - _updateUplimits(); - } + // Apply dialect to uplimits + Component.onCompleted: { + realUplimits = [uplimits[0] * dialect.multiplier, uplimits[1] * dialect.multiplier]; } - Component.onCompleted: _updateUplimits() // Labels textContainer { - labelColors: root.colors labels: [i18nc("Graph label", "Receiving"), i18nc("Graph label", "Sending"), ""] } - // Graph options - colors: [Functions.resolveColor(Plasmoid.configuration.netDownColor), Functions.resolveColor(Plasmoid.configuration.netUpColor)] - // Initialized sensors RMComponents.NetworkInterfaceDetector { id: networkInterfaces @@ -102,15 +91,10 @@ RMBaseGraph.TwoSensorsGraph { if (typeof name === 'undefined') { continue; } - if (Plasmoid.configuration.ignoredNetworkInterfaces.indexOf(name) === -1) { + if (root.ignoredInterfaces.indexOf(name) === -1) { sensors.push("network/" + name + "/download", "network/" + name + "/upload"); } } sensorsModel.sensors = sensors; - _clear(); - } - - function _updateUplimits() { - uplimits = [Plasmoid.configuration.networkReceivingTotal * dialect.multiplier, Plasmoid.configuration.networkSendingTotal * dialect.multiplier]; } } diff --git a/package/contents/ui/components/graph/base/BaseSensorGraph.qml b/package/contents/ui/components/graph/base/BaseSensorGraph.qml index 59435a3..8f3d32a 100644 --- a/package/contents/ui/components/graph/base/BaseSensorGraph.qml +++ b/package/contents/ui/components/graph/base/BaseSensorGraph.qml @@ -17,10 +17,16 @@ Item { readonly property alias textContainer: textContainer readonly property alias sensorsModel: sensorsModel + // Graph properties + property var colors: [undefined, undefined, undefined] // Common graph settins + property var sensorsType: [] // Present because is graph settins + // Thresholds properties - property var thresholds: [undefined, undefined, undefined] - property color thresholdWarningColor: Functions.resolveColor(Plasmoid.configuration.warningColor) - property color thresholdCriticalColor: Functions.resolveColor(Plasmoid.configuration.criticalColor) + property int thresholdIndex: -1 // Sensor index used for threshold + property var thresholds: [] // ONLY USED FOR CONFIG (graph settins)! | fomart: [warning, critical] + property var realThresholds: [] // fomart: [warning, critical] + readonly property color thresholdWarningColor: Functions.resolveColor(Plasmoid.configuration.warningColor) + readonly property color thresholdCriticalColor: Functions.resolveColor(Plasmoid.configuration.criticalColor) // Labels RMBaseGraph.GraphText { @@ -28,6 +34,7 @@ Item { enabled: Plasmoid.configuration.displayment != 'never' anchors.fill: parent z: 1 + labelColors: root.colors onShowValueInLabel: { // Update labels @@ -44,7 +51,6 @@ Item { Sensors.SensorDataModel { id: sensorsModel updateRateLimit: -1 - enabled: root.visible /** * Get the value and sensor ID from sensor @@ -76,24 +82,6 @@ Item { } } - Connections { - target: root - - /** - * Re assign sensorsModel.sensors when enable visibility for right initialize it. - * This is due to an issue when set sensors and model is disabled, the sensors is never initialized - * Bug reported at : https://bugs.kde.org/show_bug.cgi?id=469234 - */ - function onVisibleChanged() { - if (!root.visible) { - return; - } - const sensors = sensorsModel.sensors; - sensorsModel.sensors = []; - sensorsModel.sensors = sensors; - } - } - // Process functions property var _insertChartData: (column, value) => {} // NOTE: this is implemented by children property var _clear: () => { @@ -145,10 +133,10 @@ Item { label.visible = false; } else { // Handle threshold value - if (typeof thresholds[index] !== 'undefined') { - if (data.value >= thresholds[index][1]) { + if (index === thresholdIndex && realThresholds.length > 0) { + if (data.value >= realThresholds[1]) { label.color = thresholdCriticalColor; - } else if (data.value >= thresholds[index][0]) { + } else if (data.value >= realThresholds[0]) { label.color = thresholdWarningColor; } else { label.color = textContainer.getTextColor(index); diff --git a/package/contents/ui/components/graph/base/GraphText.qml b/package/contents/ui/components/graph/base/GraphText.qml index 40f0ebf..280401a 100644 --- a/package/contents/ui/components/graph/base/GraphText.qml +++ b/package/contents/ui/components/graph/base/GraphText.qml @@ -2,6 +2,7 @@ import QtQuick import org.kde.plasma.plasmoid import org.kde.plasma.components as PlasmaComponents import org.kde.kirigami as Kirigami +import "../../functions.mjs" as Functions Item { id: graphText @@ -17,8 +18,10 @@ Item { // Text properties property var labels: ["", "", ""] - property var valueColors: [Kirigami.Theme.textColor, Kirigami.Theme.textColor, Kirigami.Theme.textColor] - property var labelColors: [Kirigami.Theme.highlightColor, Kirigami.Theme.textColor, Kirigami.Theme.textColor] + property var valueColors: [undefined, undefined, undefined] + property var _valueColors: [undefined, undefined, undefined] // Internal + property var labelColors: [undefiend, undefined, undefined] + property var _labelColors: [Kirigami.Theme.highlightColor, undefined, undefined] // Internal property var labelsVisibleWhenZero: [true, true, true] @@ -46,6 +49,14 @@ Item { secondLineLabel.enabled = secondLineLabel.visible = labels[1] != ""; thirdLineLabel.enabled = thirdLineLabel.visible = labels[2] != ""; } + onValueColorsChanged: { + // Resolve colors + _valueColors = valueColors.map(v => Functions.resolveColor(v)); + } + onLabelColorsChanged: { + // Resolve colors + _labelColors = labelColors.map(v => Functions.resolveColor(v)); + } // Labels Flow { @@ -230,9 +241,9 @@ Item { function getTextColor(index, isLabel = false) { if (isLabel) { - return labelColors[index] || Kirigami.Theme.textColor; + return _labelColors[index] ?? Kirigami.Theme.textColor; } - return valueColors[index] || Kirigami.Theme.textColor; + return _valueColors[index] ?? Kirigami.Theme.textColor; } function _setLabelsState(state) { if (state) { diff --git a/package/contents/ui/components/graph/base/SensorGraph.qml b/package/contents/ui/components/graph/base/SensorGraph.qml index a2aab2a..3aa2995 100644 --- a/package/contents/ui/components/graph/base/SensorGraph.qml +++ b/package/contents/ui/components/graph/base/SensorGraph.qml @@ -1,8 +1,8 @@ import QtQuick import org.kde.plasma.plasmoid import org.kde.quickcharts as Charts -import org.kde.kirigami as Kirigami import "./" as RMBaseGraph +import "../../functions.mjs" as Functions RMBaseGraph.BaseSensorGraph { id: root @@ -10,9 +10,6 @@ RMBaseGraph.BaseSensorGraph { // Aliases property alias chart: chart - // Graph properties - property color chartColor: Kirigami.Theme.highlightColor - // Graph Charts.LineChart { id: chart @@ -25,7 +22,7 @@ RMBaseGraph.BaseSensorGraph { yRange.automatic: false colorSource: Charts.SingleValueSource { - value: chartColor + value: Functions.resolveColor(colors[0]) } valueSources: [ RMBaseGraph.ArrayDataSource { diff --git a/package/contents/ui/components/graph/base/TwoSensorsGraph.qml b/package/contents/ui/components/graph/base/TwoSensorsGraph.qml index 272e265..a761772 100644 --- a/package/contents/ui/components/graph/base/TwoSensorsGraph.qml +++ b/package/contents/ui/components/graph/base/TwoSensorsGraph.qml @@ -1,25 +1,26 @@ import QtQuick import org.kde.plasma.plasmoid import org.kde.quickcharts as Charts -import org.kde.kirigami as Kirigami import "./" as RMBaseGraph +import "../../functions.mjs" as Functions RMBaseGraph.BaseSensorGraph { id: root - property var uplimits: [100, 100] + // property bool ready: true // Define if // Graph properties - property var colors: [Kirigami.Theme.highlightColor, Kirigami.Theme.textColor] property bool enableHistory: Plasmoid.configuration.historyAmount > 0 property bool secondChartVisible: true + property var uplimits: [] // ONLY USED FOR CONFIG! + property var realUplimits: [100, 100] // Bind properties changes - onUplimitsChanged: { - firstChart.yRange.to = uplimits[0]; - secondChart.yRange.to = uplimits[1]; - firstChart.yRange.automatic = uplimits[0] == 0; - secondChart.yRange.automatic = uplimits[1] == 0; + onRealUplimitsChanged: { + firstChart.yRange.to = realUplimits[0]; + secondChart.yRange.to = realUplimits[1]; + firstChart.yRange.automatic = realUplimits[0] == 0; + secondChart.yRange.automatic = realUplimits[1] == 0; } // Graphs @@ -34,7 +35,7 @@ RMBaseGraph.BaseSensorGraph { yRange.automatic: false colorSource: Charts.SingleValueSource { - value: colors[1] + value: Functions.resolveColor(colors[1]) } valueSources: [ RMBaseGraph.ArrayDataSource { @@ -54,7 +55,7 @@ RMBaseGraph.BaseSensorGraph { yRange.automatic: false colorSource: Charts.SingleValueSource { - value: colors[0] + value: Functions.resolveColor(colors[0]) } valueSources: [ RMBaseGraph.ArrayDataSource { diff --git a/package/contents/ui/config/ConfigAppearance.qml b/package/contents/ui/config/ConfigAppearance.qml index e8e218d..046f760 100644 --- a/package/contents/ui/config/ConfigAppearance.qml +++ b/package/contents/ui/config/ConfigAppearance.qml @@ -5,7 +5,7 @@ import org.kde.kirigami as Kirigami import org.kde.kcmutils as KCM import org.kde.plasma.plasmoid import org.kde.plasma.components as PlasmaComponents -import "../controls" as RMControls +import "./controls" as RMControls KCM.AbstractKCM { // Make pages fill the whole view by default @@ -20,7 +20,6 @@ KCM.AbstractKCM { property alias cfg_graphHeight: graphHeight.value property alias cfg_graphMargin: graphMargin.value property alias cfg_graphFillOpacity: graphFillOpacity.value - property var cfg_graphOrders: [] // Text property alias cfg_enableShadows: enableShadows.checked @@ -29,53 +28,15 @@ KCM.AbstractKCM { property string cfg_displayment // Colors - // > CPU - property alias cfg_cpuColor: cpuColor.value - property alias cfg_cpuTemperatureColor: cpuTemperatureColor.value - // > Memory - property alias cfg_memColor: memColor.value - property alias cfg_memSecondColor: memSecondColor.value - // > Network - property alias cfg_netDownColor: netDownColor.value - property alias cfg_netUpColor: netUpColor.value - // > GPU - property alias cfg_gpuColor: gpuColor.value - property alias cfg_gpuMemoryColor: gpuMemoryColor.value - property alias cfg_gpuTemperatureColor: gpuTemperatureColor.value - // > Disk - property alias cfg_diskReadColor: diskReadColor.value - property alias cfg_diskWriteColor: diskWriteColor.value // > Threshold property alias cfg_warningColor: warningColor.value property alias cfg_criticalColor: criticalColor.value - property var monitors: { - "cpu": { - "id": "cpu", - "name": i18nc("Chart name", "CPU"), - "icon": "cpu-symbolic" - }, - "memory": { - "id": "memory", - "name": i18nc("Chart name", "Memory"), - "icon": "memory-symbolic" - }, - "gpu": { - "id": "gpu", - "name": i18nc("Chart name", "GPU"), - "icon": "freon-gpu-temperature-symbolic" - }, - "disks": { - "id": "disks", - "name": i18nc("Chart name", "Disks I/O"), - "icon": "drive-harddisk-symbolic" - }, - "network": { - "id": "network", - "name": i18nc("Chart name", "Network"), - "icon": "network-wired-symbolic" - } - } + //#region // HACK: Present to suppress errors (https://bugs.kde.org/show_bug.cgi?id=484541) + property var cfg_graphs + property var cfg_updateInterval + property var cfg_clickActionCommand + //#endregion // Tab bar header: PlasmaComponents.TabBar { @@ -107,9 +68,6 @@ KCM.AbstractKCM { // Charts Kirigami.FormLayout { - id: graphPage - wideMode: true - QtControls.CheckBox { id: verticalLayout text: i18n("Vertical layout") @@ -204,105 +162,10 @@ KCM.AbstractKCM { return valueToText(value, locale) + "%"; } } - - // order - Item { - Kirigami.FormData.label: i18n("Charts order") - Kirigami.FormData.isSection: true - } - - ListView { - id: graphsList - anchors.left: parent.left - anchors.right: parent.right - - clip: true - interactive: false - - property int listViewHeight: 0 - implicitHeight: listViewHeight - - model: ListModel { - Component.onCompleted: cfg_graphOrders.map(id => monitors[id]).forEach(item => append(item)) - - function toJS() { - const result = []; - for (let i = 0; i < count; i++) { - result.push(get(i)); - } - return result; - } - } - - delegate: Loader { - required property var index - required property var model - - width: graphsList.width - sourceComponent: delegateComponent - - Component.onCompleted: { - graphsList.listViewHeight += height + 1; - } - } - - moveDisplaced: Transition { - YAnimator { - duration: Kirigami.Units.longDuration - easing.type: Easing.InOutQuad - } - } - - // Background - Rectangle { - z: -1 - Kirigami.Theme.colorSet: Kirigami.Theme.View - Kirigami.Theme.inherit: false - color: Kirigami.Theme.backgroundColor - anchors.fill: parent - } - - // Item - Component { - id: delegateComponent - QtControls.ItemDelegate { - id: listItem - hoverEnabled: true - Kirigami.Theme.useAlternateBackgroundColor: Kirigami.Theme.alternateBackgroundColor - - contentItem: QtLayouts.RowLayout { - spacing: Kirigami.Units.largeSpacing - - Kirigami.ListItemDragHandle { - listView: graphsList - listItem: listItem - onMoveRequested: graphsList.model.move(oldIndex, newIndex, 1) - - onDropped: { - cfg_graphOrders = graphsList.model.toJS().map(item => item.id); - } - } - - Kirigami.Icon { - source: model.icon - width: Kirigami.Units.iconSizes.smallMedium - height: width - } - PlasmaComponents.Label { - text: model.name - QtLayouts.Layout.fillWidth: true - } - } - } - } - } } // Text Kirigami.FormLayout { - id: textPage - wideMode: true - QtControls.CheckBox { id: enableShadows text: i18n("Drop shadows") @@ -323,6 +186,7 @@ KCM.AbstractKCM { QtControls.ComboBox { id: displayment Kirigami.FormData.label: i18n("Text displayment:") + QtLayouts.Layout.fillWidth: true currentIndex: -1 textRole: "label" @@ -353,6 +217,7 @@ KCM.AbstractKCM { QtControls.ComboBox { id: placement Kirigami.FormData.label: i18n("Placement:") + QtLayouts.Layout.fillWidth: true currentIndex: -1 textRole: "label" @@ -383,124 +248,6 @@ KCM.AbstractKCM { // Colors Kirigami.FormLayout { - id: colorsPage - - // Charts - Kirigami.Separator { - Kirigami.FormData.label: i18n("Charts colors") - Kirigami.FormData.isSection: true - } - - // > CPU - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "CPU") - Kirigami.FormData.isSection: true - } - - RMControls.ColorSelector { - id: cpuColor - Kirigami.FormData.label: i18nc("Chart config", "Usage:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - RMControls.ColorSelector { - id: cpuTemperatureColor - Kirigami.FormData.label: i18nc("Chart config", "Temperature:") - dialogTitle: i18nc("Chart color", "Choose text color") - } - - // > Memory - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "Memory") - Kirigami.FormData.isSection: true - } - - RMControls.ColorSelector { - id: memColor - Kirigami.FormData.label: i18nc("Chart config", "Physical:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - RMControls.ColorSelector { - id: memSecondColor - Kirigami.FormData.label: i18nc("Chart config", "Swap:") - dialogTitle: i18nc("Chart color", "Choose color of series and text") - } - - // > Network - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "Network") - Kirigami.FormData.isSection: true - } - - RMControls.ColorSelector { - id: netDownColor - Kirigami.FormData.label: i18nc("Chart config", "Receiving:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - RMControls.ColorSelector { - id: netUpColor - Kirigami.FormData.label: i18nc("Chart config", "Sending:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - - // > GPU - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "GPU") - Kirigami.FormData.isSection: true - } - - RMControls.ColorSelector { - id: gpuColor - Kirigami.FormData.label: i18nc("Chart config", "Usage:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - RMControls.ColorSelector { - id: gpuMemoryColor - Kirigami.FormData.label: i18nc("Chart config", "Memory:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - RMControls.ColorSelector { - id: gpuTemperatureColor - Kirigami.FormData.label: i18nc("Chart config", "Temperature:") - dialogTitle: i18nc("Chart color", "Choose text color") - } - - // > Disk I/O - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "Disks I/O") - Kirigami.FormData.isSection: true - } - - RMControls.ColorSelector { - id: diskReadColor - Kirigami.FormData.label: i18nc("Chart config", "Read:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - RMControls.ColorSelector { - id: diskWriteColor - Kirigami.FormData.label: i18nc("Chart config", "Write:") - dialogTitle: i18nc("Chart color", "Choose series color") - } - // Thresholds Kirigami.Separator { Kirigami.FormData.label: i18n("Threshold text colors") @@ -509,13 +256,13 @@ KCM.AbstractKCM { RMControls.ColorSelector { id: warningColor - Kirigami.FormData.label: i18n("Warning status:") - dialogTitle: i18n("Choose text color when the value is in warning status") + Kirigami.FormData.label: i18n("Warning:") + dialogTitle: i18nc("Chart color", "Choose text color") } RMControls.ColorSelector { id: criticalColor - Kirigami.FormData.label: i18n("Critical status:") - dialogTitle: i18n("Choose text color when the value is in critical status") + Kirigami.FormData.label: i18n("Critical:") + dialogTitle: i18nc("Chart color", "Choose text color") } } } diff --git a/package/contents/ui/config/ConfigData.qml b/package/contents/ui/config/ConfigData.qml deleted file mode 100644 index a375015..0000000 --- a/package/contents/ui/config/ConfigData.qml +++ /dev/null @@ -1,493 +0,0 @@ -import QtQuick -import QtQuick.Controls as QtControls -import QtQuick.Layouts as QtLayouts -import org.kde.kirigami as Kirigami -import org.kde.kcmutils as KCM -import org.kde.plasma.plasmoid -import org.kde.plasma.components as PlasmaComponents -import "../components" as RMComponents -import "../controls" as RMControls -import "../components/functions.mjs" as Functions - -KCM.AbstractKCM { - // Make pages fill the whole view by default - Kirigami.ColumnView.fillWidth: true - - // CPU - property alias cfg_cpuECoresCount: cpuECoresCount.value - - // Network - readonly property var networkDialect: Functions.getNetworkDialectInfo(Plasmoid.configuration.networkUnit, i18nc) - property var cfg_ignoredNetworkInterfaces: [] - property alias cfg_networkReceivingTotal: networkReceiving.realValue - property alias cfg_networkSendingTotal: networkSending.realValue - - // Disks I/O - property alias cfg_diskReadTotal: diskRead.realValue - property alias cfg_diskWriteTotal: diskWrite.realValue - - // GPU - property string cfg_gpuIndex - - // Thresholds - property alias cfg_thresholdWarningCpuTemp: thresholdWarningCpuTemp.realValue - property alias cfg_thresholdCriticalCpuTemp: thresholdCriticalCpuTemp.realValue - property alias cfg_thresholdWarningMemory: thresholdWarningMemory.value - property alias cfg_thresholdCriticalMemory: thresholdCriticalMemory.value - property alias cfg_thresholdWarningGpuTemp: thresholdWarningGpuTemp.realValue - property alias cfg_thresholdCriticalGpuTemp: thresholdCriticalGpuTemp.realValue - - readonly property var networkSpeedOptions: [ - { - "label": i18n("Custom"), - "value": -1 - }, - { - "label": i18n("Automatic"), - "value": 0.0 - }, - { - "label": "100 " + networkDialect.kiloChar + networkDialect.suffix, - "value": 100.0 - }, - { - "label": "1 M" + networkDialect.suffix, - "value": 1000.0 - }, - { - "label": "10 M" + networkDialect.suffix, - "value": 10000.0 - }, - { - "label": "100 M" + networkDialect.suffix, - "value": 100000.0 - }, - { - "label": "1 G" + networkDialect.suffix, - "value": 1000000.0 - }, - { - "label": "2.5 G" + networkDialect.suffix, - "value": 2500000.0 - }, - { - "label": "5 G" + networkDialect.suffix, - "value": 5000000.0 - }, - { - "label": "10 G" + networkDialect.suffix, - "value": 10000000.0 - } - ] - readonly property var diskSpeedOptions: [ - { - "label": i18n("Custom"), - "value": -1 - }, - { - "label": i18n("Automatic"), - "value": 0.0 - }, - { - "label": "10 MiB/s", - "value": 10000.0 - }, - { - "label": "100 MiB/s", - "value": 100000.0 - }, - { - "label": "200 MiB/s", - "value": 200000.0 - }, - { - "label": "500 MiB/s", - "value": 500000.0 - }, - { - "label": "1 GiB/s", - "value": 1000000.0 - }, - { - "label": "2 GiB/s", - "value": 2000000.0 - }, - { - "label": "5 GiB/s", - "value": 5000000.0 - }, - { - "label": "10 GiB/s", - "value": 10000000.0 - } - ] - - // Detect network interfaces - RMComponents.NetworkInterfaceDetector { - id: networkInterfaces - } - // Detect GPU cards - RMComponents.GpuDetector { - id: gpuCards - - onReady: gpuCardSelector.select() - } - - // Tab bar - header: PlasmaComponents.TabBar { - id: bar - - PlasmaComponents.TabButton { - icon.name: "settings" - icon.height: Kirigami.Units.iconSizes.smallMedium - text: i18nc("Config header", "General") - } - PlasmaComponents.TabButton { - icon.name: "dialog-warning" - icon.height: Kirigami.Units.iconSizes.smallMedium - text: i18nc("Config header", "Thresholds") - } - } - - Kirigami.ScrollablePage { - anchors.fill: parent - - QtLayouts.StackLayout { - currentIndex: bar.currentIndex - QtLayouts.Layout.fillWidth: true - - // General - Kirigami.FormLayout { - wideMode: true - - // CPU - Kirigami.Separator { - Kirigami.FormData.label: i18nc("Chart name", "CPU") - Kirigami.FormData.isSection: true - QtLayouts.Layout.minimumWidth: 200 // Prevent too small inputs - } - - // Define Number of E-Cores, it's used for separating Intel - // E-cores and P-Cores when calculating CPU frequency, - // because they have different frequencies. - RMControls.SpinBox { - id: cpuECoresCount - Kirigami.FormData.label: i18n("E-cores") - QtLayouts.Layout.fillWidth: true - } - Kirigami.InlineMessage { - visible: true - QtLayouts.Layout.fillWidth: true - text: i18n("Intel 12+ gen Only
Define number of E-Cores your CPU have. This is for separating from P-Cores in cpu frequency.") - } - - // Network - Kirigami.Separator { - Kirigami.FormData.label: i18nc("Chart name", "Network") - Kirigami.FormData.isSection: true - } - - // Interfaces - QtLayouts.GridLayout { - Kirigami.FormData.label: i18n("Network interfaces:") - QtLayouts.Layout.fillWidth: true - - columns: 2 - rowSpacing: Kirigami.Units.smallSpacing - columnSpacing: Kirigami.Units.largeSpacing - - Repeater { - model: networkInterfaces - QtControls.CheckBox { - readonly property string interfaceName: model.SensorId.replace('network/', '').replace('/network', '') - readonly property bool ignoredByDefault: { - return /^(docker|tun|tap)(\d+)/.test(interfaceName); // Ignore docker and tun/tap networks - } - - text: interfaceName - checked: cfg_ignoredNetworkInterfaces.indexOf(interfaceName) == -1 && !ignoredByDefault - enabled: !ignoredByDefault - - onClicked: { - var ignoredNetworkInterfaces = cfg_ignoredNetworkInterfaces.slice(0); // copy() - if (checked) { - // Checking, and thus removing from the ignoredNetworkInterfaces - var i = ignoredNetworkInterfaces.indexOf(interfaceName); - ignoredNetworkInterfaces.splice(i, 1); - } else { - // Unchecking, and thus adding to the ignoredNetworkInterfaces - ignoredNetworkInterfaces.push(interfaceName); - } - cfg_ignoredNetworkInterfaces = ignoredNetworkInterfaces; - } - } - } - } - - // Transfer speed - Item { - Kirigami.FormData.label: i18n("Maximum transfer speed") - Kirigami.FormData.isSection: true - } - - RMControls.PredefinedSpinBox { - id: networkReceiving - Kirigami.FormData.label: i18nc("Chart config", "Receiving:") - QtLayouts.Layout.fillWidth: true - QtLayouts.Layout.minimumWidth: predefinedChoices.currentIndex == 0 ? 300 : 0 - factor: 1000 - - predefinedChoices { - textRole: "label" - valueRole: "value" - model: networkSpeedOptions - } - - spinBox { - decimals: 3 - stepSize: 1 - minimumValue: 0.001 - - textFromValue: function (value, locale) { - return spinBox.valueToText(value, locale) + " M" + networkDialect.suffix; - } - } - } - - RMControls.PredefinedSpinBox { - id: networkSending - Kirigami.FormData.label: i18nc("Chart config", "Sending:") - QtLayouts.Layout.fillWidth: true - QtLayouts.Layout.minimumWidth: predefinedChoices.currentIndex == 0 ? 300 : 0 - factor: 1000 - - predefinedChoices { - textRole: "label" - valueRole: "value" - model: networkSpeedOptions - } - - spinBox { - decimals: 3 - stepSize: 1 - minimumValue: 0.001 - - textFromValue: function (value, locale) { - return spinBox.valueToText(value, locale) + " M" + networkDialect.suffix; - } - } - } - - // Disk I/O - Kirigami.Separator { - Kirigami.FormData.label: i18nc("Chart name", "Disks I/O") - Kirigami.FormData.isSection: true - } - - Item { - Kirigami.FormData.label: i18n("Maximum transfer speed") - Kirigami.FormData.isSection: true - } - - RMControls.PredefinedSpinBox { - id: diskRead - Kirigami.FormData.label: i18nc("Chart config", "Read:") - QtLayouts.Layout.fillWidth: true - QtLayouts.Layout.minimumWidth: predefinedChoices.currentIndex == 0 ? 300 : 0 - factor: 1000 - - predefinedChoices { - textRole: "label" - valueRole: "value" - model: diskSpeedOptions - } - - spinBox { - decimals: 3 - stepSize: 1 - minimumValue: 0.001 - - textFromValue: function (value, locale) { - return spinBox.valueToText(value, locale) + " M" + networkDialect.suffix; - } - } - } - - RMControls.PredefinedSpinBox { - id: diskWrite - Kirigami.FormData.label: i18nc("Chart config", "Write:") - QtLayouts.Layout.fillWidth: true - QtLayouts.Layout.minimumWidth: predefinedChoices.currentIndex == 0 ? 300 : 0 - factor: 1000 - - predefinedChoices { - textRole: "label" - valueRole: "value" - model: diskSpeedOptions - } - - spinBox { - decimals: 3 - stepSize: 1 - minimumValue: 0.001 - - textFromValue: function (value, locale) { - return spinBox.valueToText(value, locale) + " M" + networkDialect.suffix; - } - } - } - - // GPU - Kirigami.Separator { - Kirigami.FormData.label: i18nc("Config header", "Graphic card") - Kirigami.FormData.isSection: true - } - - QtControls.ComboBox { - id: gpuCardSelector - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Graphic card:") - - currentIndex: -1 - textRole: "name" - valueRole: "index" - model: gpuCards.model - - onActivated: cfg_gpuIndex = currentValue - function select() { - currentIndex = indexOfValue(cfg_gpuIndex); - } - } - } - - // Thresholds - Kirigami.FormLayout { - id: thresholdsPage - wideMode: true - - property double kirigamiWidth: preferredWidth * 2 + Kirigami.Units.largeSpacing - property double preferredWidth: { - const minimumWidth = Math.max(80, warningHeader.contentWidth, criticalHeader.contentWidth); - return Math.max(minimumWidth, - // CPU - thresholdWarningCpuTemp.implicitWidth, thresholdCriticalCpuTemp.implicitWidth, - // Memory - thresholdWarningMemory.implicitWidth, thresholdCriticalMemory.implicitWidth, - // Memory - thresholdWarningMemory.implicitWidth, thresholdCriticalMemory.implicitWidth, - // GPU - thresholdWarningGpuTemp.implicitWidth, thresholdCriticalGpuTemp.implicitWidth); - } - - // Header - QtLayouts.RowLayout { - QtLayouts.Layout.fillWidth: true - spacing: Kirigami.Units.largeSpacing - - PlasmaComponents.Label { - id: warningHeader - text: i18n("Warning") - font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.2 - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - } - - PlasmaComponents.Label { - id: criticalHeader - text: i18n("Critical") - font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.2 - } - } - - // CPU Temperature - QtLayouts.RowLayout { - Kirigami.FormData.label: i18n("CPU Temperature:") - QtLayouts.Layout.preferredWidth: thresholdsPage.kirigamiWidth - spacing: Kirigami.Units.largeSpacing - - RMControls.SpinBox { - id: thresholdWarningCpuTemp - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - decimals: 1 - stepSize: 1 - minimumValue: 0.1 - maximumValue: 120 - - textFromValue: function (value, locale) { - return valueToText(value, locale) + " °C"; - } - } - RMControls.SpinBox { - id: thresholdCriticalCpuTemp - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - decimals: 1 - stepSize: 1 - minimumValue: 0.1 - maximumValue: 120 - - textFromValue: function (value, locale) { - return valueToText(value, locale) + " °C"; - } - } - } - - // Memory usage - QtLayouts.RowLayout { - Kirigami.FormData.label: i18n("Physical Memory Usage:") - QtLayouts.Layout.preferredWidth: thresholdsPage.kirigamiWidth - spacing: Kirigami.Units.largeSpacing - - RMControls.SpinBox { - id: thresholdWarningMemory - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - - textFromValue: function (value, locale) { - return value + " %"; - } - } - RMControls.SpinBox { - id: thresholdCriticalMemory - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - - textFromValue: function (value, locale) { - return value + " %"; - } - } - } - - // GPU Temperature - QtLayouts.RowLayout { - Kirigami.FormData.label: i18n("GPU Temperature:") - QtLayouts.Layout.preferredWidth: thresholdsPage.kirigamiWidth - spacing: Kirigami.Units.largeSpacing - - RMControls.SpinBox { - id: thresholdWarningGpuTemp - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - - decimals: 1 - stepSize: 1 - minimumValue: 0.1 - maximumValue: 120 - - textFromValue: function (value, locale) { - return valueToText(value, locale) + " °C"; - } - } - RMControls.SpinBox { - id: thresholdCriticalGpuTemp - QtLayouts.Layout.preferredWidth: thresholdsPage.preferredWidth - - decimals: 1 - stepSize: 1 - minimumValue: 0.1 - maximumValue: 120 - - textFromValue: function (value, locale) { - return valueToText(value, locale) + " °C"; - } - } - } - } - } - } -} diff --git a/package/contents/ui/config/ConfigGeneral.qml b/package/contents/ui/config/ConfigGeneral.qml deleted file mode 100644 index 36db18c..0000000 --- a/package/contents/ui/config/ConfigGeneral.qml +++ /dev/null @@ -1,433 +0,0 @@ -import QtQuick -import QtQuick.Controls as QtControls -import QtQuick.Layouts as QtLayouts -import org.kde.kirigami as Kirigami -import org.kde.kcmutils as KCM -import org.kde.plasma.plasmoid -import org.kde.plasma.components as PlasmaComponents -import "../components" as RMComponents -import "../controls" as RMControls - -KCM.AbstractKCM { - // Make pages fill the whole view by default - Kirigami.ColumnView.fillWidth: true - - // Charts - property alias cfg_updateInterval: updateInterval.realValue - // property int cfg_updateInterval - // > CPU - property string cfg_cpuUnit - property bool showCpuMonitor: cfg_cpuUnit !== "none" - property string cfg_cpuClockType - property string cfg_cpuClockAgregator - property alias cfg_showCpuTemperature: showCpuTemperature.checked - // property bool cfg_showCpuTemperature - // > Memory - property string cfg_memoryUnit - property string cfg_memorySecondUnit - // > Network - property string cfg_networkUnit - // > GPU - property bool cfg_showGpuMonitor - property string cfg_gpuMemoryUnit - property alias cfg_showGpuTemperature: showGpuTemperature.checked - // property bool cfg_showGpuTemperature - // > Disks I/O - property bool cfg_showDiskMonitor - - // Click action - property alias cfg_clickActionCommand: clickActionCommand.text - - // Tab bar - header: PlasmaComponents.TabBar { - id: bar - - PlasmaComponents.TabButton { - icon.name: "settings" - icon.height: Kirigami.Units.iconSizes.smallMedium - text: i18nc("Config header", "General") - } - PlasmaComponents.TabButton { - icon.name: "input-mouse-symbolic" - icon.height: Kirigami.Units.iconSizes.smallMedium - text: i18nc("Config header", "Click action") - } - } - - Kirigami.ScrollablePage { - anchors.fill: parent - - QtLayouts.StackLayout { - currentIndex: bar.currentIndex - QtLayouts.Layout.fillWidth: true - - // General - Kirigami.FormLayout { - wideMode: true - - RMControls.SpinBox { - id: updateInterval - Kirigami.FormData.label: i18n("Update interval:") - QtLayouts.Layout.fillWidth: true - - decimals: 1 - minimumValue: 0.1 - maximumValue: 3600.0 - stepSize: Math.round(0.1 * factor) - - textFromValue: function (value, locale) { - return i18n("%1 seconds", valueToText(value, locale)); - } - } - - // Charts - Kirigami.Separator { - Kirigami.FormData.label: i18nc("Config header", "Charts") - Kirigami.FormData.isSection: true - } - - // CPU - Item { - Kirigami.FormData.label: i18nc("Chart name", "CPU") - Kirigami.FormData.isSection: true - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Visibility:") - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "none" - }, - { - "label": i18n("Total usage"), - "value": "usage" - }, - { - "label": i18n("System usage"), - "value": "system" - }, - { - "label": i18n("User usage"), - "value": "user" - } - ] - - onActivated: cfg_cpuUnit = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_cpuUnit) - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Second Line:") - enabled: showCpuMonitor - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "none" - }, - { - "label": i18n("Classic/P-cores clock frequency"), - "value": "classic" - }, - { - "label": i18n("E-cores clock frequency"), - "value": "ecores" - } - ] - - onActivated: cfg_cpuClockType = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_cpuClockType) - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Clock aggregator:") - enabled: showCpuMonitor - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18nc("Agregator", "Average"), - "value": "average" - }, - { - "label": i18nc("Agregator", "Minimum"), - "value": "minimum" - }, - { - "label": i18nc("Agregator", "Maximum"), - "value": "maximum" - } - ] - - onActivated: cfg_cpuClockAgregator = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_cpuClockAgregator) - } - - QtControls.CheckBox { - id: showCpuTemperature - text: i18n("Show temperature") - enabled: showCpuMonitor - } - - // Memory - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "Memory") - Kirigami.FormData.isSection: true - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Visibility:") - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "none" - }, - { - "label": i18n("Physical memory (in KiB)"), - "value": "physical" - }, - { - "label": i18n("Physical memory (in %)"), - "value": "physical-percent" - }, - { - "label": i18n("Application memory (in KiB)"), - "value": "application" - }, - { - "label": i18n("Application memory (in %)"), - "value": "application-percent" - } - ] - - onActivated: cfg_memoryUnit = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_memoryUnit) - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Second line:") - enabled: cfg_memoryUnit !== "none" - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "none" - }, - { - "label": i18n("Swap"), - "value": "swap" - }, - { - "label": i18n("Swap (in %)"), - "value": "swap-percent" - }, - { - "label": i18n("Memory (in %)"), - "value": "memory-percent" - } - ] - - onActivated: cfg_memorySecondUnit = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_memorySecondUnit) - } - - // Network - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "Network") - Kirigami.FormData.isSection: true - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Visibility:") - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "none" - }, - { - "label": i18n("In kibibyte (KiB/s)"), - "value": "kibibyte" - }, - { - "label": i18n("In kilobit (Kbps)"), - "value": "kilobit" - }, - { - "label": i18n("In kilobyte (KBps)"), - "value": "kilobyte" - } - ] - - onActivated: cfg_networkUnit = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_networkUnit) - } - - // GPU - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "GPU") - Kirigami.FormData.isSection: true - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Visibility:") - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": false - }, - { - "label": i18n("Visible"), - "value": true - } - ] - - onActivated: cfg_showGpuMonitor = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_showGpuMonitor) - } - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Second Line:") - enabled: cfg_showGpuMonitor - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "none" - }, - { - "label": i18n("Memory (in KiB)"), - "value": "memory" - }, - { - "label": i18n("Memory (in %)"), - "value": "memory-percent" - } - ] - - onActivated: cfg_gpuMemoryUnit = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_gpuMemoryUnit) - } - QtControls.CheckBox { - id: showGpuTemperature - text: i18n("Show temperature") - enabled: cfg_showGpuMonitor - } - - // Disk I/O - Rectangle { - height: Kirigami.Units.largeSpacing - color: "transparent" - } - Item { - Kirigami.FormData.label: i18nc("Chart name", "Disks I/O") - Kirigami.FormData.isSection: true - } - - QtControls.ComboBox { - QtLayouts.Layout.fillWidth: true - Kirigami.FormData.label: i18n("Visibility:") - - currentIndex: -1 - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": false - }, - { - "label": i18n("Visible"), - "value": true - } - ] - - onActivated: cfg_showDiskMonitor = currentValue - Component.onCompleted: currentIndex = indexOfValue(cfg_showDiskMonitor) - } - } - - // Click action - Kirigami.FormLayout { - wideMode: true - - RMControls.PredefinedTextField { - id: clickActionCommand - Kirigami.FormData.label: i18nc("Chart config", "Action:") - QtLayouts.Layout.fillWidth: true - customValueIndex: 1 - - predefinedChoices { - textRole: "label" - valueRole: "value" - model: [ - { - "label": i18n("Disabled"), - "value": "" - }, - { - "label": i18n("Custom command"), - "value": "." // Prevent collide with "disabled" state - }, - { - "label": i18n("Open Plasma system monitor"), - "value": "plasma-systemmonitor" - } - ] - } - } - Kirigami.InlineMessage { - visible: clickActionCommand.predefinedChoices.currentIndex == 1 - QtLayouts.Layout.fillWidth: true - text: i18n("Command wich be executed, but this have some limitation like \"kioclient exec\" or other similar command not work.") - } - } - } - } -} diff --git a/package/contents/ui/config/ConfigGraph.qml b/package/contents/ui/config/ConfigGraph.qml new file mode 100644 index 0000000..f0eaae7 --- /dev/null +++ b/package/contents/ui/config/ConfigGraph.qml @@ -0,0 +1,419 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import org.kde.kcmutils as KCM +import org.kde.plasma.plasmoid +import org.kde.plasma.components as PlasmaComponents +import "../components" as RMComponents +import "../components/functions.mjs" as Functions +import "./controls" as RMControls + +KCM.ScrollViewKCM { + id: root + // HACK: Provides footer separator + extraFooterTopPadding: true + + // Config properties + property var cfg_graphs: "[]" + property var graphs: JSON.parse(cfg_graphs) || [] // Parssed representation of "cfg_graphs" + // TODO: handle "_v" changes + + //#region // HACK: Present to suppress errors (https://bugs.kde.org/show_bug.cgi?id=484541) + property var cfg_verticalLayout + property var cfg_historyAmount + property var cfg_customGraphWidth + property var cfg_graphWidth + property var cfg_customGraphHeight + property var cfg_graphHeight + property var cfg_graphMargin + property var cfg_graphFillOpacity + property var cfg_enableShadows + property var cfg_fontScale + property var cfg_placement + property var cfg_displayment + property var cfg_warningColor + property var cfg_criticalColor + property var cfg_updateInterval + property var cfg_clickActionCommand + //#endregion + + // Uncomment for development + /* Component.onCompleted: { + addGraph("gpu"); + addGraph("network"); + addGraph("disks"); + } */ + + // Graphs infos amd default values + readonly property var graphInfos: { + "cpu": { + "name": i18nc("Chart name", "CPU"), + "icon": "cpu-symbolic", + "default": { + "colors": ["highlightColor", "textColor", "textColor"], + "sensorsType": ["usage", "clock", false], + "clockAgregator": "average", + "eCoresCount": "", + "thresholds": [85, 105] + } + }, + "memory": { + "name": i18nc("Chart name", "Memory"), + "icon": "memory-symbolic", + "default": { + "colors": ["highlightColor", "negativeTextColor"], + "sensorsType": ["physical", "swap"], + "thresholds": [70, 90] + } + }, + "gpu": { + "name": i18nc("Chart name", "GPU"), + "icon": "freon-gpu-temperature-symbolic", + "default": { + "colors": ["highlightColor", "positiveTextColor", "textColor"], + "sensorsType": ["memory", false], + // "gpuIndex" defined in "addGraph" + "thresholds": [70, 90] + } + }, + "network": { + "name": i18nc("Chart name", "Network"), + "icon": "network-wired-symbolic", + "default": { + "colors": ["highlightColor", "positiveTextColor"], + "sensorsType": ["kibibyte"], + "uplimits": [100000, 100000], + "ignoredInterfaces": [] + } + }, + "disks": { + "name": i18nc("Chart name", "Disks I/O"), + "icon": "drive-harddisk-symbolic", + "default": { + "colors": ["highlightColor", "positiveTextColor"], + "uplimits": [200000, 200000] + } + } + } + + // List GPU cards + RMComponents.GpuDetector { + id: gpuCards + } + + // Content + view: ListView { + id: graphsView + clip: true + reuseItems: true + + //? Use differrent array due to QML issue with deep object conversion + model: ListModel { + Component.onCompleted: { + Object.values(graphs).forEach(v => append({ + type: v.type + })); + } + } + + delegate: Item { + // External item required to make Kirigami.ListItemDragHandle work + width: graphsView.width + implicitHeight: graphItem.implicitHeight + + QQC2.ItemDelegate { + id: graphItem + width: graphsView.width + hoverEnabled: true + Kirigami.Theme.useAlternateBackgroundColor: Kirigami.Theme.alternateBackgroundColor + + down: false // Disable press effect + + contentItem: RowLayout { + Kirigami.ListItemDragHandle { + listItem: graphItem + listView: graphsView + + onMoveRequested: (oldIndex, newIndex) => { + graphsView.model.move(oldIndex, newIndex, 1); + root.graphs.splice(newIndex, 0, root.graphs.splice(oldIndex, 1)[0]); + } + onDropped: root.saveGraphs() + } + + // Content + Kirigami.Icon { + source: graphInfos[model.type].icon + width: Kirigami.Units.iconSizes.smallMedium + height: width + } + QQC2.Label { + id: name + Layout.fillWidth: true + text: graphInfos[model.type].name + textFormat: Text.PlainText + } + + // Actions + DelegateButton { + icon.name: "edit-entry-symbolic" + text: i18nc("@info:tooltip", "Edit %1 graph", name.text) + + onClicked: { + editDialog.openFor(index); + } + } + DelegateButton { + icon.name: "edit-delete" + text: i18nc("@info:tooltip", "Delete %1 graph", name.text) + + onClicked: { + removePrompt.graphIndex = index; + removePrompt.graphName = name.text; + removePrompt.open(); + } + } + } + } + } + + // Animation + highlightMoveDuration: Kirigami.Units.longDuration + displaced: Transition { + YAnimator { + duration: Kirigami.Units.longDuration + } + } + + Kirigami.PlaceholderMessage { + anchors.centerIn: parent + width: parent.width - (Kirigami.Units.largeSpacing * 4) + visible: graphsView.count === 0 + + icon.name: "office-chart-line-stacked" + text: i18n("No graph selected") + explanation: i18nc("@info", "Click %1 to get started", addButton.text) + } + } + + footer: RowLayout { + spacing: Kirigami.Units.smallSpacing + + QQC2.Button { + id: addButton + // HACK: Footer comes with margin + Layout.leftMargin: Kirigami.Units.largeSpacing - 6 + + text: i18n("Add graph…") + icon.name: "list-add-symbolic" + onClicked: addDialog.open() + } + } + + // Edit dialog + Kirigami.Dialog { + id: editDialog + width: graphsView.width - Kirigami.Units.gridUnit * 4 + height: graphsView.height + + title: i18nc("@title:window", "Edit graph") + standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel + + property int graphIndex + + property bool needSave: false + onAccepted: { + if (needSave) { + graphs[graphIndex] = contentItem.item.item; + saveGraphs(); + } + } + + Loader { + id: contentItem + onLoaded: { + editDialog.open(); + item.onChanged.connect(onChanged); + } + + // Handle config change + function onChanged() { + editDialog.needSave = true; + } + } + + /** + * Open edit modal for specific graph + * @param {number} index The graph index + */ + function openFor(index) { + const item = graphs[index]; + const filename = "Edit" + (item.type.charAt(0).toUpperCase() + item.type.slice(1)); + const source = `./parts/${filename}.qml`; + + // Load settings page + let props = { + item + }; + if (item.type === "gpu") { + props.gpuCards = gpuCards.model; + } + graphIndex = index; + contentItem.setSource(source, props); + } + } + + // Add dialog + Kirigami.Dialog { + id: addDialog + width: graphsView.width - Kirigami.Units.gridUnit * 4 + height: graphsView.height - Kirigami.Units.gridUnit * 4 + + title: i18nc("@title:window", "Add graph") + + property bool needSave: false + onClosed: needSave && root.saveGraphs() + + ListView { + id: addGraphView + + model: ListModel { + Component.onCompleted: { + Object.entries(graphInfos).forEach(([k, v]) => { + append({ + type: k, + name: v.name, + icon: v.icon + }); + }); + } + } + + // clip: true + reuseItems: true + + delegate: Kirigami.SwipeListItem { + width: addGraphView.width + // Disable when graph is already present + enabled: !root.graphExist(model.type) + + contentItem: RowLayout { + // Content + Kirigami.Icon { + source: model.icon + width: Kirigami.Units.iconSizes.smallMedium + height: width + } + QQC2.Label { + Layout.fillWidth: true + text: model.name + textFormat: Text.PlainText + elide: Text.ElideRight + + opacity: enabled ? 1 : 0.6 + } + + // Actions + DelegateButton { + icon.name: "list-add-symbolic" + text: i18n("Add") + hoverEnabled: enabled + + onClicked: { + addGraph(model.type); + addDialog.needSave = true; + } + } + } + } + } + } + + // Remove dialog + Kirigami.PromptDialog { + id: removePrompt + + property int graphIndex: -1 + property string graphName: "" + + title: i18nc("@title:window", "Remove graph") + subtitle: i18nc("%1 is an graph name", "Do you want remove graph '%1'?", graphName) + + standardButtons: Kirigami.Dialog.Cancel + customFooterActions: [ + Kirigami.Action { + text: i18n("Delete graph") + icon.name: "edit-delete" + onTriggered: { + graphsView.model.remove(removePrompt.graphIndex, 1); + root.graphs.splice(removePrompt.graphIndex, 1); + root.saveGraphs(); + removePrompt.close(); + } + } + ] + } + + // Action button + component DelegateButton: QQC2.ToolButton { + display: QQC2.AbstractButton.IconOnly + QQC2.ToolTip.text: text + QQC2.ToolTip.visible: hovered + } + + // utils functions + /** + * Save graph changes + */ + function saveGraphs() { + cfg_graphs = JSON.stringify(graphs); + } + + /** + * Check if graph of an specified type exist + * @param {string} type The graph type want to be checked + * @returns {boolean} The graph already exist or not + */ + function graphExist(type) { + for (let i = 0; i < graphsView.count; i++) { + if (graphsView.model.get(i).type === type) { + return true; + } + } + return false; + } + + /** + * Add an new graph + * @param {string} type The graph type want to be added + */ + function addGraph(type) { + // Retrieve default values and check if type is valid + let defaultVals = graphInfos[type]?.default; + if (typeof defaultVals === "undefined") { + return; + } + + // Add constants (done manualy for have constatns at first) + let item = { + _v: 1, + type + }; + //? Foreach due to can't use spredd in QML + Object.entries(defaultVals).forEach(([k, v]) => item[k] = v); + + // Define "gpuIndex" on "gpu" type + if (type === "gpu") { + item.gpuIndex = (gpuCards.model[0] ?? { + index: "unknown" + }).index; + } + + // Add graph to lists + graphs.push(item); + graphsView.model.append({ + type: type + }); + } +} diff --git a/package/contents/ui/config/ConfigMisc.qml b/package/contents/ui/config/ConfigMisc.qml new file mode 100644 index 0000000..f4a1d41 --- /dev/null +++ b/package/contents/ui/config/ConfigMisc.qml @@ -0,0 +1,81 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import org.kde.kcmutils as KCM +import org.kde.plasma.plasmoid +import org.kde.plasma.components as PlasmaComponents +import "../components" as RMComponents +import "../components/functions.mjs" as Functions +import "./controls" as RMControls + +KCM.SimpleKCM { + // Config properties + property alias cfg_updateInterval: updateInterval.realValue + property alias cfg_clickActionCommand: clickActionCommand.text + + //#region // HACK: Present to suppress errors (https://bugs.kde.org/show_bug.cgi?id=484541) + property var cfg_graphs + property var cfg_verticalLayout + property var cfg_historyAmount + property var cfg_customGraphWidth + property var cfg_graphWidth + property var cfg_customGraphHeight + property var cfg_graphHeight + property var cfg_graphMargin + property var cfg_graphFillOpacity + property var cfg_enableShadows + property var cfg_fontScale + property var cfg_placement + property var cfg_displayment + property var cfg_warningColor + property var cfg_criticalColor + //#endregion + + Kirigami.FormLayout { + RMControls.SpinBox { + id: updateInterval + Kirigami.FormData.label: i18n("Update interval:") + Layout.fillWidth: true + + decimals: 1 + minimumValue: 0.1 + maximumValue: 3600.0 + stepSize: Math.round(0.1 * factor) + + textFromValue: (value, locale) => i18n("%1 seconds", valueToText(value, locale)) + } + + // Click action + RMControls.PredefinedTextField { + id: clickActionCommand + Kirigami.FormData.label: i18nc("Chart config", "Click action:") + Layout.fillWidth: true + customValueIndex: 1 + + predefinedChoices { + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("Disabled"), + "value": "" + }, + { + "label": i18n("Custom command"), + "value": "." // Prevent collide with "disabled" state + }, + { + "label": i18n("Open Plasma system monitor"), + "value": "plasma-systemmonitor" + } + ] + } + } + Kirigami.InlineMessage { + visible: clickActionCommand.predefinedChoices.currentIndex == 1 + Layout.fillWidth: true + text: i18n("Command will be executed, but may have some limitations like \"kioclient exec\" or other similar command not work.") + } + } +} diff --git a/package/contents/ui/controls/ColorSelector.qml b/package/contents/ui/config/controls/ColorSelector.qml similarity index 100% rename from package/contents/ui/controls/ColorSelector.qml rename to package/contents/ui/config/controls/ColorSelector.qml diff --git a/package/contents/ui/controls/CustomizableSize.qml b/package/contents/ui/config/controls/CustomizableSize.qml similarity index 100% rename from package/contents/ui/controls/CustomizableSize.qml rename to package/contents/ui/config/controls/CustomizableSize.qml diff --git a/package/contents/ui/controls/PredefinedSpinBox.qml b/package/contents/ui/config/controls/PredefinedSpinBox.qml similarity index 97% rename from package/contents/ui/controls/PredefinedSpinBox.qml rename to package/contents/ui/config/controls/PredefinedSpinBox.qml index 425a29a..2e57d95 100644 --- a/package/contents/ui/controls/PredefinedSpinBox.qml +++ b/package/contents/ui/config/controls/PredefinedSpinBox.qml @@ -50,6 +50,7 @@ QtLayouts.RowLayout { RMControls.SpinBox { id: spinBox QtLayouts.Layout.fillWidth: true + QtLayouts.Layout.minimumWidth: 120 visible: predefinedChoices.currentIndex === customValueIndex } diff --git a/package/contents/ui/controls/PredefinedTextField.qml b/package/contents/ui/config/controls/PredefinedTextField.qml similarity index 100% rename from package/contents/ui/controls/PredefinedTextField.qml rename to package/contents/ui/config/controls/PredefinedTextField.qml diff --git a/package/contents/ui/controls/SpinBox.qml b/package/contents/ui/config/controls/SpinBox.qml similarity index 100% rename from package/contents/ui/controls/SpinBox.qml rename to package/contents/ui/config/controls/SpinBox.qml diff --git a/package/contents/ui/config/controls/Thresholds.qml b/package/contents/ui/config/controls/Thresholds.qml new file mode 100644 index 0000000..5f81bd3 --- /dev/null +++ b/package/contents/ui/config/controls/Thresholds.qml @@ -0,0 +1,68 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import org.kde.plasma.components as PlasmaComponents +import "../controls" as RMControls + +RowLayout { + id: root + spacing: Kirigami.Units.largeSpacing + + property alias warningSpinBox: warningSpinBox + property alias criticalSpinBox: criticalSpinBox + property alias valueToText: warningSpinBox.valueToText + + // Properties + property var values: [] + property int decimals: 0 + property int stepSize: 1 + property real minimumValue: 0 + property real maximumValue + property var textFromValue: valueToText + + Component.onCompleted: { + warningSpinBox.realValue = values[0] + criticalSpinBox.realValue = values[1] + } + + RMControls.SpinBox { + id: warningSpinBox + Layout.fillWidth: true + Layout.fillHeight: true + QQC2.ToolTip.text: i18n("Warning threshold") + QQC2.ToolTip.visible: hovered + + // realValue: root.values[0] + onRealValueChanged: { + root.values[0] = realValue + root.valuesChanged() + } + + decimals: root.decimals + stepSize: root.stepSize + minimumValue: root.minimumValue + maximumValue: root.maximumValue + textFromValue: root.textFromValue + } + + RMControls.SpinBox { + id: criticalSpinBox + Layout.fillWidth: true + Layout.fillHeight: true + QQC2.ToolTip.text: i18n("Critical threshold") + QQC2.ToolTip.visible: hovered + + // realValue: values[1] + onRealValueChanged: { + root.values[1] = realValue + root.valuesChanged() + } + + decimals: root.decimals + stepSize: root.stepSize + minimumValue: root.minimumValue + maximumValue: root.maximumValue + textFromValue: root.textFromValue + } +} diff --git a/package/contents/ui/config/parts/EditCpu.qml b/package/contents/ui/config/parts/EditCpu.qml new file mode 100644 index 0000000..cc77568 --- /dev/null +++ b/package/contents/ui/config/parts/EditCpu.qml @@ -0,0 +1,194 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import org.kde.plasma.components as PlasmaComponents +import "../controls" as RMControls + +Kirigami.FormLayout { + id: root + + signal changed // Notify some settings as been changed + + /** + * Settings format: + * { + * "_v": 1, // Version of data (for compatibility) + * "type": "cpu", + * "colors": ["usageColor", "clockColor", "tempColor"], + * "sensorsType": ["usage", "clock", temperature], // Values: "usage/system/user" | "none/classic/ecores" | true/false + * "thresholds": [0, 0], // Temperature + * "clockAgregator": "average", // Values: average, minimum, maximum + * "eCoresCount": 0 + * } + */ + required property var item + + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("Total usage"), + "value": "usage" + }, + { + "label": i18n("System usage"), + "value": "system" + }, + { + "label": i18n("User usage"), + "value": "user" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.sensorsType[0]) + onActivated: { + item.sensorsType[0] = currentValue; + root.changed(); + } + } + + // Clock + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("Disabled"), + "value": "none" + }, + { + "label": i18n("Classic/P-cores clock frequency"), + "value": "classic" + }, + { + "label": i18n("E-cores clock frequency"), + "value": "ecores" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.sensorsType[1]) + onActivated: { + item.sensorsType[1] = currentValue; + root.changed(); + } + } + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Clock aggregator:") + + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18nc("Agregator", "Average"), + "value": "average" + }, + { + "label": i18nc("Agregator", "Minimum"), + "value": "minimum" + }, + { + "label": i18nc("Agregator", "Maximum"), + "value": "maximum" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.clockAgregator) + onActivated: { + item.clockAgregator = currentValue; + root.changed(); + } + } + // TODO: find way to show only when detect "e-cores" (maybe: compare first and last core frequency) + // Define Number of E-Cores, it's used for separating Intel + // E-cores and P-Cores when calculating CPU frequency, + // because they have different frequencies. + RMControls.SpinBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("E-cores") + from: 0 + to: 100 + + realValue: item.eCoresCount + onRealValueChanged: { + item.eCoresCount = value; + root.changed(); + } + + QQC2.ToolTip.text: i18nc("@info:tooltip", "For Intel 12+ gen only
Number of E-Cores your CPU have, it's for seperate it from P-Cores in frequency average calculation.") + QQC2.ToolTip.visible: hovered + } + + QQC2.CheckBox { + text: i18n("Show temperature") + checked: item.sensorsType[2] + onClicked: { + item.sensorsType[2] = checked; + root.changed(); + } + } + + RMControls.Thresholds { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Temperature threshold:") + + values: item.thresholds + onValuesChanged: { + item.thresholds = values; + root.changed(); + } + + decimals: 1 + stepSize: 1 + minimumValue: 0.1 + maximumValue: 120 + textFromValue: (value, locale) => valueToText(value, locale) + " °C" + } + + // Colors + Kirigami.Separator { + Kirigami.FormData.label: i18n("Colors") + Kirigami.FormData.isSection: true + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + dialogTitle: i18nc("Chart color", "Choose series color") + + value: item.colors[0] + onValueChanged: { + item.colors[0] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + dialogTitle: i18nc("Chart color", "Choose text color") + + value: item.colors[1] + onValueChanged: { + item.colors[1] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Third Line:") + dialogTitle: i18nc("Chart color", "Choose text color") + + value: item.colors[2] + onValueChanged: { + item.colors[2] = value; + root.changed(); + } + } +} diff --git a/package/contents/ui/config/parts/EditDisks.qml b/package/contents/ui/config/parts/EditDisks.qml new file mode 100644 index 0000000..3b36823 --- /dev/null +++ b/package/contents/ui/config/parts/EditDisks.qml @@ -0,0 +1,152 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import "../controls" as RMControls + +Kirigami.FormLayout { + id: root + + signal changed // Notify some settings as been changed + + /** + * Settings format: + * { + * "_v": 1, // Version of data (for compatibility) + * "type": "disks", + * "colors": ["readColor", "writeColor"], + * "uplimits": [0, 0] // Chart1, Chart2 + * } + */ + required property var item + + // TODO: translate units + readonly property var speedOptions: [ + { + "label": i18n("Custom"), + "value": -1 + }, + { + "label": i18n("Automatic"), + "value": 0.0 + }, + { + "label": "10 MiB/s", + "value": 10000.0 + }, + { + "label": "100 MiB/s", + "value": 100000.0 + }, + { + "label": "200 MiB/s", + "value": 200000.0 + }, + { + "label": "500 MiB/s", + "value": 500000.0 + }, + { + "label": "1 GiB/s", + "value": 1000000.0 + }, + { + "label": "2 GiB/s", + "value": 2000000.0 + }, + { + "label": "5 GiB/s", + "value": 5000000.0 + }, + { + "label": "10 GiB/s", + "value": 10000000.0 + } + ] + + // Transfer speed + Item { + Kirigami.FormData.label: i18n("Maximum transfer speed") + Kirigami.FormData.isSection: true + } + RMControls.PredefinedSpinBox { + id: readSpeed + Layout.fillWidth: true + Kirigami.FormData.label: i18nc("Chart config", "Read:") + factor: 1000 + + realValue: item.uplimits[0] + onRealValueChanged: { + item.uplimits[0] = readSpeed.realValue; + root.changed(); + } + + predefinedChoices { + textRole: "label" + valueRole: "value" + model: speedOptions + } + + spinBox { + decimals: 3 + stepSize: 1 + minimumValue: 0.001 + + textFromValue: (value, locale) => spinBox.valueToText(value, locale) + " MiB/s" + } + } + RMControls.PredefinedSpinBox { + id: writeSpeed + Layout.fillWidth: true + Kirigami.FormData.label: i18nc("Chart config", "Write:") + factor: 1000 + + realValue: item.uplimits[1] + onRealValueChanged: { + item.uplimits[1] = writeSpeed.realValue; + root.changed(); + } + + predefinedChoices { + textRole: "label" + valueRole: "value" + model: speedOptions + } + + spinBox { + decimals: 3 + stepSize: 1 + minimumValue: 0.001 + + textFromValue: (value, locale) => spinBox.valueToText(value, locale) + " MiB/s" + } + } + + // Colors + Kirigami.Separator { + Kirigami.FormData.label: i18n("Colors") + Kirigami.FormData.isSection: true + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + dialogTitle: i18nc("Chart color", "Choose series color") + + value: item.colors[0] + onValueChanged: { + item.colors[0] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + dialogTitle: i18nc("Chart color", "Choose text color") + + value: item.colors[1] + onValueChanged: { + item.colors[1] = value; + root.changed(); + } + } +} diff --git a/package/contents/ui/config/parts/EditGpu.qml b/package/contents/ui/config/parts/EditGpu.qml new file mode 100644 index 0000000..b42c856 --- /dev/null +++ b/package/contents/ui/config/parts/EditGpu.qml @@ -0,0 +1,136 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import "../controls" as RMControls + +Kirigami.FormLayout { + id: root + + signal changed // Notify some settings as been changed + + /** + * Settings format: + * { + * "_v": 1, // Version of data (for compatibility) + * "type": "gpu", + * "colors": ["usageColor", "memoryColor", "tempColor"], + * "sensorsType": ["memory", temperature], // Values: "none/memory/memory-percent" | true/false + * "gpuIndex": "gpu0", + * "thresholds": [0, 0], // Temperature + * } + */ + required property var item + required property var gpuCards // contains list of GPUs + + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Graphic card:") + + currentIndex: -1 + textRole: "name" + valueRole: "index" + model: gpuCards + + Component.onCompleted: currentIndex = indexOfValue(item.gpuIndex) + onActivated: { + item.gpuIndex = currentValue; + root.changed(); + } + } + + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + + currentIndex: -1 + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("Disabled"), + "value": "none" + }, + { + "label": i18n("Memory (in KiB)"), + "value": "memory" + }, + { + "label": i18n("Memory (in %)"), + "value": "memory-percent" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.sensorsType[0]) + onActivated: { + item.sensorsType[0] = currentValue; + root.changed(); + } + } + + QQC2.CheckBox { + id: showGpuTemperature + text: i18n("Show temperature") + checked: item.sensorsType[1] + onClicked: { + item.sensorsType[1] = checked; + root.changed(); + } + } + + RMControls.Thresholds { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Temperature threshold:") + + values: item.thresholds + onValuesChanged: { + item.thresholds = values; + root.changed(); + } + + decimals: 1 + stepSize: 1 + minimumValue: 0.1 + maximumValue: 120 + textFromValue: (value, locale) => valueToText(value, locale) + " °C" + } + + // Colors + Kirigami.Separator { + Kirigami.FormData.label: i18n("Colors") + Kirigami.FormData.isSection: true + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + dialogTitle: i18nc("Chart color", "Choose series color") + + value: item.colors[0] + onValueChanged: { + item.colors[0] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + dialogTitle: i18nc("Chart color", "Choose text color") + + value: item.colors[1] + onValueChanged: { + item.colors[1] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Third Line:") + dialogTitle: i18nc("Chart color", "Choose text color") + + value: item.colors[2] + onValueChanged: { + item.colors[2] = value; + root.changed(); + } + } +} diff --git a/package/contents/ui/config/parts/EditMemory.qml b/package/contents/ui/config/parts/EditMemory.qml new file mode 100644 index 0000000..4cf4ef6 --- /dev/null +++ b/package/contents/ui/config/parts/EditMemory.qml @@ -0,0 +1,132 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import "../controls" as RMControls + +Kirigami.FormLayout { + id: root + + signal changed // Notify some settings as been changed + + /** + * Settings format: + * { + * "_v": 1, // Version of data (for compatibility) + * "type": "memory", + * "colors": ["memoryColor", "swapColor"], + * "sensorsType": ["memory", "swap"], // Values: "physical/physical-percent/application/application-percent" | "none/swap/swap-percent/memory-percent" + * "thresholds": [0, 0], // Usage + * } + */ + required property var item + + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("Physical memory (in KiB)"), + "value": "physical" + }, + { + "label": i18n("Physical memory (in %)"), + "value": "physical-percent" + }, + { + "label": i18n("Application memory (in KiB)"), + "value": "application" + }, + { + "label": i18n("Application memory (in %)"), + "value": "application-percent" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.sensorsType[0]) + onActivated: { + item.sensorsType[0] = currentValue; + root.changed(); + } + } + + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second line:") + + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("Disabled"), + "value": "none" + }, + { + "label": i18n("Swap"), + "value": "swap" + }, + { + "label": i18n("Swap (in %)"), + "value": "swap-percent" + }, + { + "label": i18n("Memory (in %)"), + "value": "memory-percent" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.sensorsType[1]) + onActivated: { + item.sensorsType[1] = currentValue; + root.changed(); + } + } + + RMControls.Thresholds { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Usage threshold:") + + values: item.thresholds + onValuesChanged: { + item.thresholds = values; + root.changed(); + } + + decimals: 1 + stepSize: 1 + minimumValue: 0.1 + maximumValue: 100 + textFromValue: (value, locale) => valueToText(value, locale) + " %" + } + + // Colors + Kirigami.Separator { + Kirigami.FormData.label: i18n("Colors") + Kirigami.FormData.isSection: true + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + dialogTitle: i18nc("Chart color", "Choose series color") + + value: item.colors[0] + onValueChanged: { + item.colors[0] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + dialogTitle: i18nc("Chart color", "Choose series color") + + value: item.colors[1] + onValueChanged: { + item.colors[1] = value; + root.changed(); + } + } +} diff --git a/package/contents/ui/config/parts/EditNetwork.qml b/package/contents/ui/config/parts/EditNetwork.qml new file mode 100644 index 0000000..5392f69 --- /dev/null +++ b/package/contents/ui/config/parts/EditNetwork.qml @@ -0,0 +1,225 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls as QQC2 +import org.kde.kirigami as Kirigami +import "../controls" as RMControls +import "../../components" as RMComponents +import "../../components/functions.mjs" as Functions + +Kirigami.FormLayout { + id: root + + signal changed // Notify some settings as been changed + + /** + * Settings format: + * { + * "_v": 1, // Version of data (for compatibility) + * "type": "network", + * "colors": ["receivingColor", "sendingColor"], + * "sensorsType": ["dialect"], // Values: "kibibyte/kilobit/kilobyte" + * "uplimits": [0, 0], // Chart1, Chart2 + * "ignoredInterfaces": [] + * } + */ + required property var item + + readonly property var dialect: Functions.getNetworkDialectInfo(item.sensorsType[0], i18nc) + readonly property var speedOptions: [ + { + "label": i18n("Custom"), + "value": -1 + }, + { + "label": i18n("Automatic"), + "value": 0.0 + }, + { + "label": "100 " + dialect.kiloChar + dialect.suffix, + "value": 100.0 + }, + { + "label": "1 M" + dialect.suffix, + "value": 1000.0 + }, + { + "label": "10 M" + dialect.suffix, + "value": 10000.0 + }, + { + "label": "100 M" + dialect.suffix, + "value": 100000.0 + }, + { + "label": "1 G" + dialect.suffix, + "value": 1000000.0 + }, + { + "label": "2.5 G" + dialect.suffix, + "value": 2500000.0 + }, + { + "label": "5 G" + dialect.suffix, + "value": 5000000.0 + }, + { + "label": "10 G" + dialect.suffix, + "value": 10000000.0 + } + ] + + // List network interfaces + RMComponents.NetworkInterfaceDetector { + id: networkInterfaces + } + + QQC2.ComboBox { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Dialect:") + + textRole: "label" + valueRole: "value" + model: [ + { + "label": i18n("kibibyte (KiB/s)"), + "value": "kibibyte" + }, + { + "label": i18n("kilobit (Kbps)"), + "value": "kilobit" + }, + { + "label": i18n("kilobyte (KBps)"), + "value": "kilobyte" + } + ] + + Component.onCompleted: currentIndex = indexOfValue(item.sensorsType[0]) + onActivated: { + item.sensorsType[0] = currentValue; + root.changed(); + } + } + + // Interfaces + GridLayout { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Network interfaces:") + + columns: 2 + rowSpacing: Kirigami.Units.smallSpacing + columnSpacing: Kirigami.Units.largeSpacing + + Repeater { + model: networkInterfaces + QQC2.CheckBox { + readonly property string interfaceName: model.SensorId.replace('network/', '').replace('/network', '') + readonly property bool ignoredByDefault: { + return /^(docker|tun|tap)(\d+)/.test(interfaceName); // Ignore docker and tun/tap networks + } + + text: interfaceName + checked: item.ignoredInterfaces.indexOf(interfaceName) == -1 && !ignoredByDefault + enabled: !ignoredByDefault + + onClicked: { + if (checked) { + // Checking, and thus removing from the ignoredNetworkInterfaces + var i = item.ignoredInterfaces.indexOf(interfaceName); + item.ignoredInterfaces.splice(i, 1); + } else { + // Unchecking, and thus adding to the ignoredNetworkInterfaces + item.ignoredInterfaces.push(interfaceName); + } + root.changed(); + } + } + } + } + + // Transfer speed + Item { + Kirigami.FormData.label: i18n("Maximum transfer speed") + Kirigami.FormData.isSection: true + } + RMControls.PredefinedSpinBox { + id: receivingSpeed + Layout.fillWidth: true + Kirigami.FormData.label: i18nc("Chart config", "Receiving:") + factor: 1000 + + realValue: item.uplimits[0] + onRealValueChanged: { + item.uplimits[0] = receivingSpeed.realValue; + root.changed(); + } + + predefinedChoices { + textRole: "label" + valueRole: "value" + model: speedOptions + } + + spinBox { + decimals: 3 + stepSize: 1 + minimumValue: 0.001 + + textFromValue: (value, locale) => spinBox.valueToText(value, locale) + " M" + dialect.suffix + } + } + RMControls.PredefinedSpinBox { + id: sendingSpeed + Layout.fillWidth: true + Kirigami.FormData.label: i18nc("Chart config", "Sending:") + factor: 1000 + + realValue: item.uplimits[1] + onRealValueChanged: { + item.uplimits[1] = sendingSpeed.realValue; + root.changed(); + } + + predefinedChoices { + textRole: "label" + valueRole: "value" + model: speedOptions + } + + spinBox { + decimals: 3 + stepSize: 1 + minimumValue: 0.001 + + textFromValue: (value, locale) => spinBox.valueToText(value, locale) + " M" + dialect.suffix + } + } + + // Colors + Kirigami.Separator { + Kirigami.FormData.label: i18n("Colors") + Kirigami.FormData.isSection: true + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("First line:") + dialogTitle: i18nc("Chart color", "Choose series color") + + value: item.colors[0] + onValueChanged: { + item.colors[0] = value; + root.changed(); + } + } + RMControls.ColorSelector { + Layout.fillWidth: true + Kirigami.FormData.label: i18n("Second Line:") + dialogTitle: i18nc("Chart color", "Choose text color") + + value: item.colors[1] + onValueChanged: { + item.colors[1] = value; + root.changed(); + } + } +} diff --git a/package/contents/ui/controls/CustomizableAmount.qml b/package/contents/ui/controls/CustomizableAmount.qml deleted file mode 100644 index dcb2ba1..0000000 --- a/package/contents/ui/controls/CustomizableAmount.qml +++ /dev/null @@ -1,15 +0,0 @@ -import QtQuick -import org.kde.kirigami as Kirigami -import "./" as RMControls - -RMControls.SpinBox { - id: customizableSize - - property bool customized - - // Customized checkbox - enabled: Kirigami.FormData.checked - Kirigami.FormData.checkable: true - Kirigami.FormData.checked: customized - onEnabledChanged: customized = enabled -} diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 315fcd7..442014f 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -26,6 +26,7 @@ import "./components/graph" as RMGraph PlasmoidItem { id: root + readonly property int graphVersion: 1 //? Bump when some settings changes in "graphs" structure readonly property bool vertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical // Settings properties @@ -40,12 +41,14 @@ PlasmoidItem { property double itemWidth: _getCustomConfig("graphWidth", Math.round(initWidth * (verticalLayout ? 1 : 1.5))) property double itemHeight: _getCustomConfig("graphHeight", Math.round(initWidth)) property double fontPixelSize: Math.round(verticalLayout ? (itemHeight / 1.4 * fontScale) : (itemHeight * fontScale)) + property var graphsModel: (JSON.parse(Plasmoid.configuration.graphs) || []).filter(v => v._v === graphVersion) // Initialize JS functions Component.onCompleted: Functions.init(Kirigami.Theme) // Content - preferredRepresentation: fullRepresentation + Plasmoid.configurationRequired: graphsModel.length === 0 // Check if graphs is valid and have some items + preferredRepresentation: Plasmoid.configurationRequired ? compactRepresentation : fullRepresentation fullRepresentation: MouseArea { Layout.preferredWidth: !verticalLayout ? (itemWidth * graphView.model.length + itemMargin * (graphView.model.length + 1)) : itemWidth Layout.preferredHeight: verticalLayout ? (itemHeight * graphView.model.length + itemMargin * (graphView.model.length + 1)) : itemHeight @@ -93,24 +96,13 @@ PlasmoidItem { spacing: itemMargin orientation: verticalLayout ? ListView.Vertical : ListView.Horizontal interactive: false + reuseItems: true - model: Plasmoid.configuration.graphOrders.filter(item => { - if (item === "cpu") { - return Plasmoid.configuration.cpuUnit !== "none"; - } else if (item === "disks") { - return Plasmoid.configuration.showDiskMonitor; - } else if (item === "gpu") { - return Plasmoid.configuration.showGpuMonitor; - } else if (item === "memory") { - return Plasmoid.configuration.memoryUnit !== "none"; - } else if (item === "network") { - return Plasmoid.configuration.networkUnit !== "none"; - } - return false; - }) + // TODO: Better handle "graphs" change + model: graphsModel delegate: Loader { - source: _graphIdToFilename(modelData) + required property var modelData width: itemWidth height: itemHeight @@ -120,6 +112,17 @@ PlasmoidItem { item.textContainer.secondLineLabel.font.pixelSize = Qt.binding(() => root.fontPixelSize); item.textContainer.thirdLineLabel.font.pixelSize = Qt.binding(() => root.fontPixelSize); } + Component.onCompleted: { + const filename = (modelData.type.charAt(0).toUpperCase() + modelData.type.slice(1)) + "Graph"; + const source = `./components/graph/${filename}.qml`; + + // Remove internal props + delete modelData._v; + delete modelData.type; + + // Load graph + setSource(source, modelData); + } } function getGraph(index) { @@ -129,11 +132,6 @@ PlasmoidItem { } } - function _graphIdToFilename(graphId) { - const filename = (graphId.charAt(0).toUpperCase() + graphId.slice(1)) + "Graph"; - return "./components/graph/" + filename + ".qml"; - } - function _getCustomConfig(property, fallback) { if (Plasmoid.configuration[`custom${property.charAt(0).toUpperCase() + property.slice(1)}`]) { return Plasmoid.configuration[property];