From 7afb6f966e782831d99faf5e791793109e32bec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Eduardo=20Garc=C3=ADa=20M=C3=A1rquez?= Date: Tue, 24 Feb 2026 10:39:48 -0500 Subject: [PATCH] feat: CPU control widget using powerprofilesctl KDE Plasma 6 panel widget for Intel CPU monitoring and profile switching. Shows temperature, performance %, turbo state. Uses system's power-profiles-daemon instead of custom scripts. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 3 + README.md | 54 +++++++++++++++ contents/ui/main.qml | 152 +++++++++++++++++++++++++++++++++++++++++++ install.sh | 24 +++++++ metadata.desktop | 14 ++++ metadata.json | 20 ++++++ 6 files changed, 267 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 contents/ui/main.qml create mode 100755 install.sh create mode 100644 metadata.desktop create mode 100644 metadata.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..42f60eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.bak +*.tmp +.directory diff --git a/README.md b/README.md new file mode 100644 index 0000000..e0ec95a --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# KDE Plasma CPU Control Widget + +Widget de KDE Plasma 6 para monitorear y controlar el rendimiento del CPU Intel desde el panel. + +## Características + +- Temperatura del CPU en tiempo real en el panel +- Porcentaje de rendimiento y estado del turbo boost +- Cambio de perfil con un click: + - **Performance**: Máximo rendimiento (videollamadas, compilación) + - **Balanced**: Equilibrio rendimiento/consumo (uso general) + - **Power Saver**: Bajo consumo (batería, temperaturas altas) +- Usa `powerprofilesctl` (estándar del sistema, sin sudo) +- Colores indicadores de temperatura y estado + +## Requisitos + +- KDE Plasma 6 +- CPU Intel con driver `intel_pstate` +- `power-profiles-daemon` (incluido por defecto en Kubuntu) + +## Instalación + +```bash +chmod +x install.sh +./install.sh +kquitapp6 plasmashell && kstart plasmashell +``` + +Click derecho en el panel > "Add Widgets..." > Buscar "CPU Control" + +## Desinstalación + +```bash +rm -rf ~/.local/share/plasma/plasmoids/org.kde.plasma.cpucontrol +kquitapp6 plasmashell && kstart plasmashell +``` + +## Estructura + +``` +cpu-control-plasmoid/ +├── metadata.json +├── metadata.desktop +├── contents/ +│ └── ui/ +│ └── main.qml +├── install.sh +└── README.md +``` + +## Licencia + +MIT diff --git a/contents/ui/main.qml b/contents/ui/main.qml new file mode 100644 index 0000000..08849b6 --- /dev/null +++ b/contents/ui/main.qml @@ -0,0 +1,152 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import org.kde.plasma.plasmoid 2.0 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +Item { + id: root + + property string currentTemp: "..." + property string currentProfile: "..." + property string maxPerf: "..." + property string turboState: "..." + + Plasmoid.preferredRepresentation: Plasmoid.compactRepresentation + + Timer { + interval: 3000 + running: true + repeat: true + triggeredOnStart: true + onTriggered: readStatus.connectSource(readStatus.cmd) + } + + PlasmaCore.DataSource { + id: readStatus + engine: "executable" + property string cmd: "echo $(cat /sys/class/thermal/thermal_zone0/temp):$(powerprofilesctl get):$(cat /sys/devices/system/cpu/intel_pstate/max_perf_pct):$(cat /sys/devices/system/cpu/intel_pstate/no_turbo)" + + onNewData: { + var out = data["stdout"].trim() + var p = out.split(":") + if (p.length >= 4) { + root.currentTemp = Math.round(parseInt(p[0]) / 1000) + "°C" + root.currentProfile = p[1] + root.maxPerf = p[2] + "%" + root.turboState = p[3] === "0" ? "ON" : "OFF" + } + disconnectSource(sourceName) + } + } + + PlasmaCore.DataSource { + id: runCmd + engine: "executable" + onNewData: { + disconnectSource(sourceName) + readStatus.connectSource(readStatus.cmd) + } + } + + function setProfile(profile) { + runCmd.connectSource("powerprofilesctl set " + profile) + } + + Plasmoid.compactRepresentation: Row { + spacing: 4 + + PlasmaCore.IconItem { + source: "cpu" + width: 16 + height: 16 + anchors.verticalCenter: parent.verticalCenter + } + + PlasmaComponents.Label { + text: root.currentTemp + anchors.verticalCenter: parent.verticalCenter + } + + MouseArea { + anchors.fill: parent + onClicked: plasmoid.expanded = !plasmoid.expanded + } + } + + Plasmoid.fullRepresentation: Column { + width: 220 + spacing: 8 + + PlasmaComponents.Label { + text: "CPU Control" + font.bold: true + font.pointSize: 12 + anchors.horizontalCenter: parent.horizontalCenter + } + + Grid { + columns: 2 + spacing: 6 + anchors.horizontalCenter: parent.horizontalCenter + + PlasmaComponents.Label { text: "Temp:"; opacity: 0.7 } + PlasmaComponents.Label { + text: root.currentTemp + font.bold: true + color: parseInt(root.currentTemp) < 60 ? "#27ae60" : parseInt(root.currentTemp) < 75 ? "#f39c12" : "#e74c3c" + } + + PlasmaComponents.Label { text: "Perf:"; opacity: 0.7 } + PlasmaComponents.Label { text: root.maxPerf; font.bold: true } + + PlasmaComponents.Label { text: "Turbo:"; opacity: 0.7 } + PlasmaComponents.Label { + text: root.turboState + font.bold: true + color: root.turboState === "ON" ? "#27ae60" : "#e74c3c" + } + + PlasmaComponents.Label { text: "Profile:"; opacity: 0.7 } + PlasmaComponents.Label { + text: root.currentProfile + font.bold: true + color: root.currentProfile === "performance" ? "#27ae60" : root.currentProfile === "power-saver" ? "#3498db" : "#f39c12" + } + } + + Rectangle { + width: parent.width - 20 + height: 1 + color: PlasmaCore.Theme.textColor + opacity: 0.2 + anchors.horizontalCenter: parent.horizontalCenter + } + + Column { + anchors.horizontalCenter: parent.horizontalCenter + spacing: 6 + + PlasmaComponents.Button { + text: "Performance" + width: 180 + checked: root.currentProfile === "performance" + onClicked: root.setProfile("performance") + } + + PlasmaComponents.Button { + text: "Balanced" + width: 180 + checked: root.currentProfile === "balanced" + onClicked: root.setProfile("balanced") + } + + PlasmaComponents.Button { + text: "Power Saver" + width: 180 + checked: root.currentProfile === "power-saver" + onClicked: root.setProfile("power-saver") + } + } + } +} diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..c7452fd --- /dev/null +++ b/install.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Instalar CPU Control Plasmoid + +PLASMOID_DIR="$HOME/.local/share/plasma/plasmoids/org.kde.plasma.cpucontrol" + +echo "Instalando CPU Control Plasmoid..." + +# Crear directorio si no existe +mkdir -p "$PLASMOID_DIR" + +# Copiar archivos +cp -r "$(dirname "$0")"/* "$PLASMOID_DIR/" + +# Remover el script de instalación del destino +rm -f "$PLASMOID_DIR/install.sh" +rm -f "$PLASMOID_DIR/README.md" + +echo "Instalado en: $PLASMOID_DIR" +echo "" +echo "Para usar:" +echo "1. Reinicia Plasma: kquitapp6 plasmashell && kstart plasmashell" +echo "2. Click derecho en panel > Add Widgets > Buscar 'CPU Control'" +echo "" +echo "O reinicia sesión para que los cambios tomen efecto." diff --git a/metadata.desktop b/metadata.desktop new file mode 100644 index 0000000..8c01e51 --- /dev/null +++ b/metadata.desktop @@ -0,0 +1,14 @@ +[Desktop Entry] +Name=CPU Control +Comment=Control CPU performance mode +Icon=cpu +Type=Service +X-KDE-ServiceTypes=Plasma/Applet +X-Plasma-API=declarativeappletscript +X-Plasma-MainScript=ui/main.qml +X-KDE-PluginInfo-Name=org.kde.plasma.cpucontrol +X-KDE-PluginInfo-Category=System Information +X-KDE-PluginInfo-Author=Andres Garcia +X-KDE-PluginInfo-Email=andresgarcia0313@gmail.com +X-KDE-PluginInfo-Version=1.0.0 +X-KDE-PluginInfo-License=MIT diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..5131b5d --- /dev/null +++ b/metadata.json @@ -0,0 +1,20 @@ +{ + "KPlugin": { + "Id": "org.kde.plasma.cpucontrol", + "Name": "CPU Control", + "Description": "Control CPU performance mode", + "Icon": "cpu", + "Authors": [ + { + "Name": "Andres Garcia", + "Email": "andresgarcia0313@gmail.com" + } + ], + "Category": "System Information", + "License": "MIT", + "Version": "1.0.0", + "Website": "https://github.com/andresgarcia0313" + }, + "KPackageStructure": "Plasma/Applet", + "X-Plasma-API-Minimum-Version": "6.0" +}