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];