DesktopWidgets: add SystemStat widget

This commit is contained in:
Lysec
2026-01-31 10:36:50 +01:00
parent 131740dcc0
commit 82f9e7e89d
22 changed files with 526 additions and 2 deletions
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Tasten anzeigen",
"media-player-show-visualizer-description": "Audiovisualisierungs-Overlay anzeigen.",
"media-player-visualizer-type-description": "Wählen Sie einen Visualisierungstyp für den Hintergrund des Desktop-Medienplayers.",
"system-stat-rounded-corners-description": "Abgerundete Ecken für den Widget-Hintergrund verwenden.",
"system-stat-rounded-corners-label": "Abgerundete Ecken",
"system-stat-show-background-description": "Zeige den Hintergrundbehälter für das Systemstatistik-Widget.",
"system-stat-show-background-label": "Hintergrund anzeigen",
"system-stat-stat-type-description": "Wähle, welche Systemstatistik angezeigt werden soll.",
"system-stat-stat-type-label": "Statistiktyp",
"title": "Desktop-Widgets",
"weather-enabled-description": "Zeige ein Wetter-Widget auf dem Desktop an.",
"weather-enabled-label": "Wetter-Widget aktivieren",
+6
View File
@@ -903,6 +903,12 @@
"media-player-show-buttons-label": "Show buttons",
"media-player-show-visualizer-description": "Show the audio visualizer overlay.",
"media-player-visualizer-type-description": "Choose a visualization type.",
"system-stat-rounded-corners-description": "Use rounded corners for the widget background.",
"system-stat-rounded-corners-label": "Rounded corners",
"system-stat-show-background-description": "Show the background container for the system stat widget.",
"system-stat-show-background-label": "Show background",
"system-stat-stat-type-description": "Choose which system statistic to display.",
"system-stat-stat-type-label": "Statistic Type",
"title": "Desktop Widgets",
"weather-enabled-description": "Show a weather widget on the desktop.",
"weather-enabled-label": "Enable weather widget",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Mostrar botones",
"media-player-show-visualizer-description": "Mostrar la superposición del visualizador de audio.",
"media-player-visualizer-type-description": "Elige un tipo de visualización para el fondo del reproductor multimedia de escritorio.",
"system-stat-rounded-corners-description": "Usar esquinas redondeadas para el fondo del widget.",
"system-stat-rounded-corners-label": "Esquinas Redondeadas",
"system-stat-show-background-description": "Mostrar el contenedor de fondo para el widget de estadísticas del sistema.",
"system-stat-show-background-label": "Mostrar fondo",
"system-stat-stat-type-description": "Elige qué estadística del sistema mostrar.",
"system-stat-stat-type-label": "Tipo de Estadística",
"title": "Widgets de escritorio",
"weather-enabled-description": "Mostrar un widget del clima en el escritorio.",
"weather-enabled-label": "Activar widget del clima",
+17
View File
@@ -489,6 +489,7 @@
"week": "Semaine",
"widgets": "Widgets",
"width": "Largeur",
"windows": "Fenêtres",
"yes": "Oui"
},
"control-center": {
@@ -508,6 +509,7 @@
"on-hover": "Au survol"
},
"hide-modes": {
"auto-hide": "Masquer automatiquement ",
"hidden": "Masquer quand vide",
"idle": "Masquer quand inactif",
"transparent": "Transparent quand vide",
@@ -560,6 +562,7 @@
"emoji-loading-description": "Veuillez patienter",
"emoji-no-recent": "Aucun emoji récent pour le moment",
"emoji-search-description": "Rechercher et copier des émojis",
"settings-search-description": "Trouvez et explorez les paramètres",
"windows-search-description": "Rechercher et focaliser les fenêtres ouvertes"
}
},
@@ -597,6 +600,7 @@
"density-default": "Défaut",
"density-mini": "Mini",
"density-spacious": "Spacieux",
"display-mode-always-visible": "Toujours Visible",
"type-floating": "Flottante",
"type-framed": "Encadrée",
"type-simple": "Simple"
@@ -718,6 +722,11 @@
"volumes-volume-overdrive-label": "Autoriser le dépassement du volume"
},
"bar": {
"appearance-auto-hide-delay-description": "Délai avant que la barre ne se masque après le départ de la souris",
"appearance-auto-hide-delay-label": "Délai de masquage ",
"appearance-auto-hide-exclusive-note": "Remarque : La zone exclusive est automatiquement désactivée lorsque le masquage automatique est actif",
"appearance-auto-show-delay-description": "Délai avant que la barre ne saffiche lorsque la souris entre en bordure",
"appearance-auto-show-delay-label": "Délai dapparition ",
"appearance-background-opacity-description": "Définir l'opacité de l'arrière-plan spécifiquement pour la barre.",
"appearance-background-opacity-label": "Opacité de l'arrière-plan de la barre",
"appearance-capsule-opacity-description": "Définir le niveau d'opacité des arrière-plans des widgets quand la capsule est affichée.",
@@ -725,6 +734,8 @@
"appearance-density-description": "Ajustez le remplissage de la barre pour un aspect compact ou spacieux.",
"appearance-density-label": "Densité de la barre",
"appearance-desc": "Personnalisez l'apparence et la position de la barre.",
"appearance-display-mode-description": "Choisir quand la barre est visible ",
"appearance-display-mode-label": "Mode daffichage ",
"appearance-floating-description": "Afficher la barre sous forme de 'pilule' flottante.",
"appearance-floating-label": "Barre flottante",
"appearance-frame-radius": "Rayon interne",
@@ -892,6 +903,12 @@
"media-player-show-buttons-label": "Afficher les boutons",
"media-player-show-visualizer-description": "Afficher la superposition de l'visualiseur audio.",
"media-player-visualizer-type-description": "Choisissez un type de visualisation pour l'arrière-plan du lecteur multimédia de bureau.",
"system-stat-rounded-corners-description": "Utiliser des coins arrondis pour l'arrière-plan du widget.",
"system-stat-rounded-corners-label": "Coins Arrondis",
"system-stat-show-background-description": "Afficher le conteneur d'arrière-plan pour le widget de statistiques système.",
"system-stat-show-background-label": "Afficher l'arrière-plan",
"system-stat-stat-type-description": "Choisis quelle statistique système afficher.",
"system-stat-stat-type-label": "Type de Statistique",
"title": "Widgets de bureau",
"weather-enabled-description": "Afficher un widget météo sur le bureau.",
"weather-enabled-label": "Activer le widget météo",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Gombok megjelenítése",
"media-player-show-visualizer-description": "Audiovizuális megjelenítő fedvény megjelenítése.",
"media-player-visualizer-type-description": "Válasszon vizualizációs típust az asztali média lejátszó hátteréhez.",
"system-stat-rounded-corners-description": "Lekerekített sarkok használata a widget hátteréhez.",
"system-stat-rounded-corners-label": "Lekerekített Sarkok",
"system-stat-show-background-description": "Mutassa a háttérkonténert a rendszerstatisztika Widgethez.",
"system-stat-show-background-label": "Háttér megjelenítése",
"system-stat-stat-type-description": "Válaszd ki, melyik rendszerstatisztikát jelenítsd meg.",
"system-stat-stat-type-label": "Statisztika Típusa",
"title": "Asztali Widgetek",
"weather-enabled-description": "Időjárás widget megjelenítése az asztalon.",
"weather-enabled-label": "Időjárás widget engedélyezése",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "ボタンを表示",
"media-player-show-visualizer-description": "オーディオビジュアライザーのオーバーレイを表示する。",
"media-player-visualizer-type-description": "デスクトップメディアプレーヤーの背景に使用するビジュアライザーの種類を選択します。",
"system-stat-rounded-corners-description": "ウィジェットの背景に丸い角を使用する。",
"system-stat-rounded-corners-label": "角丸",
"system-stat-show-background-description": "システム統計ウィジェットの背景コンテナを表示します。",
"system-stat-show-background-label": "背景を表示",
"system-stat-stat-type-description": "表示するシステム統計を選択してください。",
"system-stat-stat-type-label": "統計の種類",
"title": "デスクトップウィジェット",
"weather-enabled-description": "デスクトップに天気ウィジェットを表示します。",
"weather-enabled-label": "天気ウィジェットを有効化",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "버튼 표시",
"media-player-show-visualizer-description": "오디오 비주얼라이저 오버레이를 표시합니다.",
"media-player-visualizer-type-description": "비주얼라이저 유형을 선택하세요.",
"system-stat-rounded-corners-description": "위젯 배경에 둥근 모서리를 사용합니다.",
"system-stat-rounded-corners-label": "둥근 모서리",
"system-stat-show-background-description": "시스템 통계 위젯의 배경 컨테이너를 표시합니다.",
"system-stat-show-background-label": "배경 표시",
"system-stat-stat-type-description": "표시할 시스템 통계를 선택하세요.",
"system-stat-stat-type-label": "통계 유형",
"title": "바탕 화면 위젯",
"weather-enabled-description": "바탕 화면에 날씨 위젯을 표시합니다.",
"weather-enabled-label": "날씨 위젯 활성화",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Bişkokan nîşan bide",
"media-player-show-visualizer-description": "Vîdyoyê dîtbarîkerê dengî nîşan bide.",
"media-player-visualizer-type-description": "Choose a visualization type for the desktop media player background.",
"system-stat-rounded-corners-description": "Goşeyên girover ji bo paşxaneya widgetê bikar bînin.",
"system-stat-rounded-corners-label": "گۆشە خڕەکان",
"system-stat-show-background-description": "کۆنتێنەری پاشبنەما بۆ ویجێتی ئاماری سیستەم نیشان بدە.",
"system-stat-show-background-label": "Paşxan nîşan bide",
"system-stat-stat-type-description": "Hilbijêre kîjan statîstîka sîstemê nîşan bide.",
"system-stat-stat-type-label": "جۆری ئامار",
"title": "Alavên sermaseyê",
"weather-enabled-description": "Widjeyekî hewayê li ser sermaseyê nîşan bide.",
"weather-enabled-label": "Widgeta hewayê çalak bike",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Knoppen weergeven",
"media-player-show-visualizer-description": "Toon de audio-visualisatie overlay.",
"media-player-visualizer-type-description": "Kies een visualisatietype voor de achtergrond van de desktop mediaplayer.",
"system-stat-rounded-corners-description": "Afgeronde hoeken gebruiken voor de widget-achtergrond.",
"system-stat-rounded-corners-label": "Afgeronde Hoeken",
"system-stat-show-background-description": "Toon de achtergrondcontainer voor de systeemstatistieken-widget.",
"system-stat-show-background-label": "Achtergrond weergeven",
"system-stat-stat-type-description": "Kies welke systeemstatistiek weer te geven.",
"system-stat-stat-type-label": "Statistiektype",
"title": "Desktopwidgets",
"weather-enabled-description": "Toon een weerwidget op het bureaublad.",
"weather-enabled-label": "Weerwidget inschakelen",
+8
View File
@@ -717,6 +717,14 @@
"bar": {
"appearance-density-description": "Fastset utfylling på lina for å gjera henne tett eller romsleg."
},
"desktop-widgets": {
"system-stat-rounded-corners-description": "Bruk avrunda hjørne for bakgrunnen til widgeten.",
"system-stat-rounded-corners-label": "Avrunda Hjørne",
"system-stat-show-background-description": "Vis bakgrunnsbehaldaren for systemstatistikk-widgeten.",
"system-stat-show-background-label": "Vis bakgrunn",
"system-stat-stat-type-description": "Vel kva systemstatistikk som skal visast.",
"system-stat-stat-type-label": "Statistikktil"
},
"launcher": {
"clipboard-desc": "Sjå og styra utklippsboka di frå programveljaren.",
"execute-desc": "Styrer korleis applikasjonar er køyrde",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Pokaż przyciski",
"media-player-show-visualizer-description": "Pokaż nakładkę wizualizatora audio.",
"media-player-visualizer-type-description": "Wybierz typ wizualizacji dla tła odtwarzacza pulpitu.",
"system-stat-rounded-corners-description": "Użyj zaokrąglonych rogów dla tła widżetu.",
"system-stat-rounded-corners-label": "Zaokrąglone Narożniki",
"system-stat-show-background-description": "Pokaż kontener tła dla widżetu statystyk systemowych.",
"system-stat-show-background-label": "Pokaż tło",
"system-stat-stat-type-description": "Wybierz, którą statystykę systemową wyświetlić.",
"system-stat-stat-type-label": "Typ Statystyki",
"title": "Widżety pulpitu",
"weather-enabled-description": "Pokaż widżet pogody na pulpicie.",
"weather-enabled-label": "Włącz widżet pogody",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Mostrar botões",
"media-player-show-visualizer-description": "Mostrar a sobreposição do visualizador de áudio.",
"media-player-visualizer-type-description": "Escolha um tipo de visualização para o fundo do reprodutor de mídia na área de trabalho.",
"system-stat-rounded-corners-description": "Usar cantos arredondados para o fundo do widget.",
"system-stat-rounded-corners-label": "Cantos Arredondados",
"system-stat-show-background-description": "Mostrar o contêiner de fundo para o widget de estatísticas do sistema.",
"system-stat-show-background-label": "Mostrar plano de fundo",
"system-stat-stat-type-description": "Escolhe qual estatística do sistema exibir.",
"system-stat-stat-type-label": "Tipo de Estatística",
"title": "Widgets da área de trabalho",
"weather-enabled-description": "Mostrar um widget de clima na área de trabalho.",
"weather-enabled-label": "Ativar widget de clima",
+9
View File
@@ -489,6 +489,7 @@
"week": "Неделя",
"widgets": "Виджеты",
"width": "Ширина",
"windows": "Окна ",
"yes": "Да"
},
"control-center": {
@@ -597,6 +598,7 @@
"density-default": "По умолчанию",
"density-mini": "Мини",
"density-spacious": "Просторный",
"display-mode-always-visible": "Всегда видны",
"type-floating": "Плавающий",
"type-framed": "В рамке",
"type-simple": "Простой"
@@ -725,6 +727,7 @@
"appearance-density-description": "Настройка отступов панели для компактного или просторного вида.",
"appearance-density-label": "Плотность панели",
"appearance-desc": "Настройка внешнего вида и положения панели.",
"appearance-display-mode-label": "Режим Отображение",
"appearance-floating-description": "Отображает панель как плавающую 'таблетку'.",
"appearance-floating-label": "Плавающая панель",
"appearance-frame-radius": "Внутренний радиус",
@@ -892,6 +895,12 @@
"media-player-show-buttons-label": "Показать кнопки",
"media-player-show-visualizer-description": "Показать наложение аудиовизуализатора.",
"media-player-visualizer-type-description": "Выберите тип визуализации для фона медиаплеера.",
"system-stat-rounded-corners-description": "Использовать скругленные углы для фона виджета.",
"system-stat-rounded-corners-label": "Скругленные Углы",
"system-stat-show-background-description": "Показать фоновый контейнер для виджета системной статистики.",
"system-stat-show-background-label": "Показать фон",
"system-stat-stat-type-description": "Выберите, какую системную статистику отображать.",
"system-stat-stat-type-label": "Тип Статистики",
"title": "Настольные виджеты",
"weather-enabled-description": "Показать погодный виджет на рабочем столе.",
"weather-enabled-label": "Включить виджет погоды",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Visa knappar",
"media-player-show-visualizer-description": "Visa ljudvisualiseringsöverlägget.",
"media-player-visualizer-type-description": "Välj en visualiseringstyp.",
"system-stat-rounded-corners-description": "Använd rundade hörn för widgetbakgrunden.",
"system-stat-rounded-corners-label": "Rundade Hörn",
"system-stat-show-background-description": "Visa bakgrundsbehållaren för systemstatistik-widgeten.",
"system-stat-show-background-label": "Visa bakgrund",
"system-stat-stat-type-description": "Välj vilken systemstatistik som ska visas.",
"system-stat-stat-type-label": "Statistiktyp",
"title": "Skrivbordswidgetar",
"weather-enabled-description": "Visa en väderwidget på skrivbordet.",
"weather-enabled-label": "Aktivera väderwidget",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Düğmeleri göster",
"media-player-show-visualizer-description": "Ses görselleştirici katmanını göster.",
"media-player-visualizer-type-description": "Masaüstü medya oynatıcı arka planı için bir görselleştirme türü seçin.",
"system-stat-rounded-corners-description": "Widget arka planı için yuvarlatılmış köşeler kullan.",
"system-stat-rounded-corners-label": "Yuvarlatılmış Köşeler",
"system-stat-show-background-description": "Sistem istatistik Widget'ı için arka plan kapsayıcısını göster.",
"system-stat-show-background-label": "Arka planı göster",
"system-stat-stat-type-description": "Hangi sistem istatistiğini görüntüleyeceğini seç.",
"system-stat-stat-type-label": "İstatistik Türü",
"title": "Masaüstü araçları",
"weather-enabled-description": "Masaüstünde bir hava durumu aracı göster.",
"weather-enabled-label": "Hava durumu araç kutusunu etkinleştir",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "Показати кнопки",
"media-player-show-visualizer-description": "Показати накладання аудіовізуалізатора.",
"media-player-visualizer-type-description": "Оберіть тип візуалізації для фону медіаплеєра на робочому столі.",
"system-stat-rounded-corners-description": "Використовувати заокруглені кути для фону віджета.",
"system-stat-rounded-corners-label": "Закруглені Кути",
"system-stat-show-background-description": "Показати фоновий контейнер для віджета системної статистики.",
"system-stat-show-background-label": "Показати фон",
"system-stat-stat-type-description": "Виберіть, яку системну статистику відображати.",
"system-stat-stat-type-label": "Тип Статистики",
"title": "Настільні віджети",
"weather-enabled-description": "Показувати погодний віджет на робочому столі.",
"weather-enabled-label": "Увімкнути віджет погоди",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "显示按钮",
"media-player-show-visualizer-description": "显示音频可视化叠加层。",
"media-player-visualizer-type-description": "选择桌面媒体播放器的背景可视化类型。",
"system-stat-rounded-corners-description": "小组件背景使用圆角。",
"system-stat-rounded-corners-label": "圆角",
"system-stat-show-background-description": "显示系统统计小部件的背景容器。",
"system-stat-show-background-label": "显示背景",
"system-stat-stat-type-description": "选择要显示的系统统计信息。",
"system-stat-stat-type-label": "统计类型",
"title": "桌面小部件",
"weather-enabled-description": "在桌面上显示天气小部件。",
"weather-enabled-label": "启用天气小部件",
+6
View File
@@ -892,6 +892,12 @@
"media-player-show-buttons-label": "顯示按鈕",
"media-player-show-visualizer-description": "顯示視覺效果",
"media-player-visualizer-type-description": "選擇視覺效果的樣式",
"system-stat-rounded-corners-description": "小工具背景使用圓角。",
"system-stat-rounded-corners-label": "圓角",
"system-stat-show-background-description": "顯示系統統計小工具的背景容器。",
"system-stat-show-background-label": "顯示背景",
"system-stat-stat-type-description": "選擇要顯示的系統統計資訊。",
"system-stat-stat-type-label": "統計類型",
"title": "桌面小工具",
"weather-enabled-description": "在桌面顯示一個天氣小工具",
"weather-enabled-label": "啟用天氣小工具",
@@ -0,0 +1,128 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Modules.DesktopWidgets
import qs.Services.System
import qs.Services.UI
import qs.Widgets
DraggableDesktopWidget {
id: root
// Widget settings
readonly property var widgetMetadata: DesktopWidgetRegistry.widgetMetadata["SystemStat"]
readonly property string statType: (widgetData && widgetData.statType !== undefined) ? widgetData.statType : (widgetMetadata.statType !== undefined ? widgetMetadata.statType : "CPU")
readonly property string diskPath: (widgetData && widgetData.diskPath !== undefined) ? widgetData.diskPath : "/"
readonly property color color: (widgetData && widgetData.color !== undefined) ? widgetData.color : Color.mPrimary
// History tracking
property var history: []
readonly property int maxHistory: 60 // 60 points at 1s = 1 minute of history
implicitWidth: Math.round(240 * widgetScale)
implicitHeight: Math.round(100 * widgetScale)
width: implicitWidth
height: implicitHeight
Timer {
interval: 1000
repeat: true
running: true
triggeredOnStart: true
onTriggered: {
let val = 0;
switch (root.statType) {
case "CPU":
val = SystemStatService.cpuUsage;
break;
case "GPU":
val = SystemStatService.gpuTemp;
break;
case "Memory":
val = SystemStatService.memPercent;
break;
case "Disk":
val = SystemStatService.diskPercents[root.diskPath] || 0;
break;
case "Network":
val = Math.max(SystemStatService.rxRatio, SystemStatService.txRatio) * 100;
break;
}
let newHistory = root.history.slice();
newHistory.push(val);
if (newHistory.length > root.maxHistory) {
newHistory.shift();
}
root.history = newHistory;
}
}
RowLayout {
anchors.fill: parent
anchors.margins: Math.round(Style.marginL * widgetScale)
spacing: Math.round(Style.marginL * widgetScale)
ColumnLayout {
Layout.alignment: Qt.AlignVCenter
Layout.fillHeight: true
Layout.preferredWidth: Math.round(64 * widgetScale)
spacing: Style.marginXS * root.widgetScale
NIcon {
Layout.alignment: Qt.AlignHCenter
icon: {
switch (root.statType) {
case "CPU":
return "cpu-usage";
case "GPU":
return "gpu";
case "Memory":
return "memory";
case "Disk":
return "storage";
case "Network":
return "network";
default:
return "help";
}
}
color: root.color
pointSize: Style.fontSizeXL * root.widgetScale
}
NText {
Layout.alignment: Qt.AlignHCenter
text: {
const lastVal = root.history.length > 0 ? root.history[root.history.length - 1] : 0;
return Math.round(lastVal) + (root.statType === "GPU" ? "°C" : "%");
}
color: root.color
pointSize: Style.fontSizeS * root.widgetScale
font.weight: Style.fontWeightBold
horizontalAlignment: Text.AlignHCenter
}
NText {
Layout.alignment: Qt.AlignHCenter
visible: root.statType === "Disk" && root.diskPath !== "/"
text: root.diskPath
color: root.color
pointSize: Style.fontSizeXXS * root.widgetScale
elide: Text.ElideMiddle
Layout.maximumWidth: Math.round(56 * widgetScale)
opacity: 0.8
}
}
NGraph {
Layout.fillWidth: true
Layout.fillHeight: true
values: root.history
maxValue: 100
color: root.color
fill: true
}
}
}
@@ -0,0 +1,111 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Services.System
import qs.Widgets
ColumnLayout {
id: root
spacing: Style.marginM
width: 700
property var widgetData: null
property var widgetMetadata: null
signal settingsChanged(var settings)
property string valueStatType: widgetData.statType !== undefined ? widgetData.statType : widgetMetadata.statType
property string valueDiskPath: widgetData.diskPath !== undefined ? widgetData.diskPath : widgetMetadata.diskPath
property bool valueShowBackground: widgetData.showBackground !== undefined ? widgetData.showBackground : widgetMetadata.showBackground
property bool valueRoundedCorners: widgetData.roundedCorners !== undefined ? widgetData.roundedCorners : (widgetMetadata.roundedCorners !== undefined ? widgetMetadata.roundedCorners : true)
function saveSettings() {
var settings = Object.assign({}, widgetData || {});
settings.statType = valueStatType;
settings.diskPath = valueDiskPath;
settings.showBackground = valueShowBackground;
settings.roundedCorners = valueRoundedCorners;
return settings;
}
NComboBox {
Layout.fillWidth: true
label: I18n.tr("panels.desktop-widgets.system-stat-stat-type-label")
description: I18n.tr("panels.desktop-widgets.system-stat-stat-type-description")
currentKey: valueStatType
minimumWidth: 260 * Style.uiScaleRatio
model: [
{
"key": "CPU",
"name": I18n.tr("system-monitor.cpu-usage")
},
{
"key": "GPU",
"name": I18n.tr("panels.system-monitor.gpu-section-label")
},
{
"key": "Memory",
"name": I18n.tr("common.memory")
},
{
"key": "Network",
"name": I18n.tr("bar.system-monitor.network-traffic-label")
},
{
"key": "Disk",
"name": I18n.tr("system-monitor.disk")
}
]
onSelected: key => {
valueStatType = key;
settingsChanged(saveSettings());
}
}
NComboBox {
Layout.fillWidth: true
visible: valueStatType === "Disk"
label: I18n.tr("bar.system-monitor.disk-path-label")
description: I18n.tr("bar.system-monitor.disk-path-description")
model: {
const paths = Object.keys(SystemStatService.diskPercents).sort();
return paths.map(path => ({
key: path,
name: path
}));
}
currentKey: valueDiskPath
onSelected: key => {
valueDiskPath = key;
settingsChanged(saveSettings());
}
}
NDivider {
Layout.fillWidth: true
}
NToggle {
Layout.fillWidth: true
label: I18n.tr("panels.desktop-widgets.system-stat-show-background-label")
description: I18n.tr("panels.desktop-widgets.system-stat-show-background-description")
checked: valueShowBackground
onToggled: checked => {
valueShowBackground = checked;
settingsChanged(saveSettings());
}
}
NToggle {
Layout.fillWidth: true
visible: valueShowBackground
label: I18n.tr("panels.desktop-widgets.system-stat-rounded-corners-label")
description: I18n.tr("panels.desktop-widgets.system-stat-rounded-corners-description")
checked: valueRoundedCorners
onToggled: checked => {
valueRoundedCorners = checked;
settingsChanged(saveSettings());
}
}
}
+13 -2
View File
@@ -25,6 +25,9 @@ Singleton {
property Component weatherComponent: Component {
DesktopWeather {}
}
property Component systemStatComponent: Component {
SystemStat {}
}
// Widget registry object mapping widget names to components
// Created in Component.onCompleted to ensure Components are ready
@@ -36,6 +39,7 @@ Singleton {
widgetsObj["Clock"] = clockComponent;
widgetsObj["MediaPlayer"] = mediaPlayerComponent;
widgetsObj["Weather"] = weatherComponent;
widgetsObj["SystemStat"] = systemStatComponent;
widgets = widgetsObj;
Logger.i("DesktopWidgetRegistry", "Service started");
@@ -50,7 +54,8 @@ Singleton {
property var widgetSettingsMap: ({
"Clock": "WidgetSettings/ClockSettings.qml",
"MediaPlayer": "WidgetSettings/MediaPlayerSettings.qml",
"Weather": "WidgetSettings/WeatherSettings.qml"
"Weather": "WidgetSettings/WeatherSettings.qml",
"SystemStat": "WidgetSettings/SystemStatSettings.qml"
})
property var widgetMetadata: ({
@@ -72,6 +77,12 @@ Singleton {
},
"Weather": {
"showBackground": true
},
"SystemStat": {
"showBackground": true,
"statType": "CPU",
"diskPath": "/",
"roundedCorners": true
}
})
@@ -122,7 +133,7 @@ Singleton {
var manifest = PluginRegistry.getPluginManifest(pluginId);
return manifest ? manifest.name : pluginId;
}
// Core widgets - return as-is (Clock, MediaPlayer, Weather)
// Core widgets - return as-is (Clock, MediaPlayer, Weather, SystemStat)
return widgetId;
}
+150
View File
@@ -0,0 +1,150 @@
import QtQuick
import QtQuick.Shapes
import qs.Commons
Item {
id: root
property var values: []
property real maxValue: 100
property color color: Color.mPrimary
property real strokeWidth: 2 * Style.uiScaleRatio
property bool fill: true
property real fillOpacity: 0.15
property bool smooth: true
readonly property bool hasData: values.length >= 2
// Internal values for continuous temporal smoothing
property var smoothValues: []
Timer {
interval: 16
running: root.smooth && root.hasData
repeat: true
onTriggered: {
if (!root.values || root.values.length === 0)
return;
// Initialize if needed
if (root.smoothValues.length !== root.values.length) {
root.smoothValues = root.values.slice();
return;
}
let newValues = [];
let updated = false;
const lerpFactor = 0.10; // Balanced for responsiveness and liquid motion
for (let i = 0; i < root.values.length; i++) {
let diff = root.values[i] - root.smoothValues[i];
if (Math.abs(diff) < 0.01) {
newValues.push(root.values[i]);
} else {
newValues.push(root.smoothValues[i] + diff * lerpFactor);
updated = true;
}
}
if (updated)
root.smoothValues = newValues;
}
}
// Generate the SVG path string for a smooth curve
readonly property string curvePath: {
let rawSource = root.smooth ? root.smoothValues : root.values;
if (!rawSource || rawSource.length < 2)
return "";
// Sample to 7 stable points for an ultra-broad, sweeping look
const targetPoints = 7;
let source = [];
for (let i = 0; i < targetPoints; i++) {
let exactIdx = i * (rawSource.length - 1) / (targetPoints - 1);
let i1 = Math.floor(exactIdx);
let i2 = Math.ceil(exactIdx);
let t = exactIdx - i1;
source.push(rawSource[i1] * (1 - t) + (rawSource[i2] ?? rawSource[i1]) * t);
}
let n = source.length;
let path = `M 0 ${getY(0, source)}`;
// Standard tension for the most natural "sweeping" look
const tension = 0.5;
const k = (1 - tension) / 3;
for (let i = 0; i < n - 1; i++) {
let x1 = (i / (n - 1)) * root.width;
let y1 = getY(i, source);
let x2 = ((i + 1) / (n - 1)) * root.width;
let y2 = getY(i + 1, source);
// Control points for Centripetal Catmull-Rom style spline
let y0 = (i === 0) ? (2 * y1 - y2) : getY(i - 1, source);
let x0 = ((i - 1) / (n - 1)) * root.width;
let y3 = (i + 2 >= n) ? (2 * y2 - y1) : getY(i + 2, source);
let x3 = ((i + 2) / (n - 1)) * root.width;
let cp1x = x1 + (x2 - x0) * k;
let cp1y = y1 + (y2 - y0) * k;
let cp2x = x2 - (x3 - x1) * k;
let cp2y = y2 - (y3 - y1) * k;
path += ` C ${cp1x.toFixed(2)},${cp1y.toFixed(2)} ${cp2x.toFixed(2)},${cp2y.toFixed(2)} ${x2.toFixed(2)},${y2.toFixed(2)}`;
}
return path;
}
Shape {
id: shape
anchors.fill: parent
antialiasing: true
visible: root.hasData
ShapePath {
id: strokePath
strokeColor: root.color
strokeWidth: root.strokeWidth
fillColor: "transparent"
joinStyle: ShapePath.RoundJoin
capStyle: ShapePath.RoundCap
PathSvg {
path: root.curvePath
}
}
ShapePath {
id: fillPath
strokeColor: "transparent"
strokeWidth: 0
fillGradient: LinearGradient {
x1: 0
y1: 0
x2: 0
y2: root.height
GradientStop {
position: 0.0
color: Qt.rgba(root.color.r, root.color.g, root.color.b, root.fillOpacity)
}
GradientStop {
position: 1.0
color: "transparent"
}
}
PathSvg {
path: root.curvePath + ` L ${root.width} ${root.height} L 0 ${root.height} Z`
}
}
}
function getY(idx, source) {
if (!source || source.length === 0)
return root.height;
let i = Math.max(0, Math.min(source.length - 1, idx));
return root.height - (Math.max(0, Math.min(root.maxValue, source[i])) / root.maxValue) * root.height;
}
}