From 8beb726230b2641cfec540a48d3877532c488367 Mon Sep 17 00:00:00 2001 From: Luis Bocanegra Date: Sat, 19 Oct 2024 22:31:20 -0600 Subject: [PATCH] feat: show GPU usage next to icon closes: https://github.com/luisbocanegra/plasma-intel-gpu-monitor/issues/6 --- package/contents/config/main.xml | 18 +++ package/contents/ui/CompactRepresentation.qml | 123 ++++++++++++------ package/contents/ui/IconAndTextItem.qml | 114 ++++++++++++++++ package/contents/ui/configGeneral.qml | 42 +++++- package/contents/ui/main.qml | 20 ++- 5 files changed, 273 insertions(+), 44 deletions(-) create mode 100644 package/contents/ui/IconAndTextItem.qml diff --git a/package/contents/config/main.xml b/package/contents/config/main.xml index 347e077..05f7d9d 100644 --- a/package/contents/config/main.xml +++ b/package/contents/config/main.xml @@ -23,5 +23,23 @@ 1 + + + 1 + + + + + 1 + + + + + 0 + + + + false + diff --git a/package/contents/ui/CompactRepresentation.qml b/package/contents/ui/CompactRepresentation.qml index c5dfdc1..5ca8b23 100644 --- a/package/contents/ui/CompactRepresentation.qml +++ b/package/contents/ui/CompactRepresentation.qml @@ -1,64 +1,103 @@ import QtQuick +import QtQuick.Layouts import org.kde.kirigami as Kirigami import org.kde.plasma.core as PlasmaCore import org.kde.plasma.plasmoid +import org.kde.plasma.workspace.components as WorkspaceComponents import "components" as Components -MouseArea { - id: compact - anchors.fill: parent - property bool isPanelVertical: plasmoid.formFactor === PlasmaCore.Types.Vertical - property real itemSize: Math.min(compact.height, compact.width) +Loader { + id: compactRoot property var engineIcon property color badgeColor - property var usageNow + property var currentUsage + readonly property bool vertical: (Plasmoid.formFactor == PlasmaCore.Types.Vertical) + // 0: disable, 1: badge, 2: beside icon + readonly property int showUsageMode: Plasmoid.configuration.showUsageMode + // 0: percentage, 1: color + readonly property int badgeStyle: Plasmoid.configuration.badgeStyle + // 0: current engine, 1: total (rc6) + readonly property int usageSource: Plasmoid.configuration.usageSource + readonly property bool useBadge: showUsageMode === 1 || Plasmoid.configuration.needsToBeSquare - hoverEnabled: true - onClicked: { - main.expanded = !main.expanded + sourceComponent: (showUsageMode !== 0 && !useBadge) ? iconAndTextComponent : iconComponent + // sourceComponent: iconComponent + Layout.fillWidth: compactRoot.vertical + Layout.fillHeight: !compactRoot.vertical + Layout.minimumWidth: item.Layout.minimumWidth + Layout.minimumHeight: item.Layout.minimumHeight + + MouseArea { + id: compactMouseArea + anchors.fill: parent + + hoverEnabled: true + + onClicked: { + main.expanded = !main.expanded + } } - Item { - id: container - height: compact.itemSize - width: compact.width - anchors.centerIn: parent + Component { + id: iconComponent - Components.PlasmoidIcon { + Kirigami.Icon { id: plasmoidIcon - height: Kirigami.Units.iconSizes.roundedIconSize(Math.min(parent.width, parent.height)) - width: height - source: engineIcon - } + readonly property int minIconSize: Math.max((compactRoot.vertical ? compactRoot.width : compactRoot.height), Kirigami.Units.iconSizes.small) - Item { - id: innerRectangle - width: plasmoidIcon.width * 0.7 - height: plasmoidIcon.height * 0.7 - anchors.centerIn: parent - } + source: Plasmoid.icon + active: compactMouseArea.containsMouse + // reset implicit size, so layout in free dimension does not stop at the default one + implicitWidth: Kirigami.Units.iconSizes.small + implicitHeight: Kirigami.Units.iconSizes.small + Layout.minimumWidth: compactRoot.vertical ? Kirigami.Units.iconSizes.small : minIconSize + Layout.minimumHeight: compactRoot.vertical ? minIconSize : Kirigami.Units.iconSizes.small - Rectangle { - visible: true - anchors { - horizontalCenter: innerRectangle.right - verticalCenter: innerRectangle.bottom + WorkspaceComponents.BadgeOverlay { + anchors.bottom: parent.bottom + anchors.right: parent.right + visible: showUsageMode === 1 && badgeStyle === 0 + text: parseInt(currentUsage) + "%" + icon: parent + } + + Rectangle { + anchors.centerIn: parent + width: Math.min(plasmoidIcon.width, plasmoidIcon.height) * 0.7 + height: width + color: "transparent" + Rectangle { + anchors { + horizontalCenter: parent.right + verticalCenter: parent.bottom + } + visible: showUsageMode === 1 && badgeStyle === 1 + + property Item icon: plasmoidIcon + property real scaling: 1 + color: badgeColor + width: Math.min(parseInt(icon.height / 2.5) , 10) + height: width + radius: width / 2 + opacity: 1 + border.width: 1 + border.color: Kirigami.Theme.backgroundColor + smooth: true + } } - // visible: !isPanelVertical - - property Item icon: plasmoidIcon - property real scaling: 1 - color: badgeColor - width: Math.min(parseInt(icon.height / 2.5) , 10) - height: width - radius: width / 2 - opacity: 1 - border.width: 1 - border.color: Kirigami.Theme.backgroundColor //PlasmaCore.ColorScope.backgroundColor - smooth: true } } + Component { + id: iconAndTextComponent + + IconAndTextItem { + vertical: compactRoot.vertical + iconSource: Plasmoid.icon + active: compactMouseArea.containsMouse + text: parseInt(currentUsage) + "%" + } + } } diff --git a/package/contents/ui/IconAndTextItem.qml b/package/contents/ui/IconAndTextItem.qml new file mode 100644 index 0000000..c5c5914 --- /dev/null +++ b/package/contents/ui/IconAndTextItem.qml @@ -0,0 +1,114 @@ +/* + * SPDX-FileCopyrightText: 2018 Friedrich W. H. Kossebau + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import QtQuick + +import QtQuick.Layouts + +import org.kde.kirigami as Kirigami +import org.kde.plasma.components as PlasmaComponents + +GridLayout { + id: iconAndTextRoot + + property alias iconSource: icon.source + property alias text: label.text + property bool vertical: false // too bad we cannot make this an enum + property alias active: icon.active + + readonly property int minimumIconSize: Kirigami.Units.iconSizes.small + readonly property int iconSize: iconAndTextRoot.vertical ? width : height + + columns: iconAndTextRoot.vertical ? 1 : 2 + rows: iconAndTextRoot.vertical ? 2 : 1 + + columnSpacing: 0 + rowSpacing: 0 + + Kirigami.Icon { + id: icon + + readonly property int implicitMinimumIconSize: Math.max(iconSize, minimumIconSize) + // reset implicit size, so layout in free dimension does not stop at the default one + implicitWidth: minimumIconSize + implicitHeight: minimumIconSize + + Layout.fillWidth: iconAndTextRoot.vertical + Layout.fillHeight: !iconAndTextRoot.vertical + Layout.minimumWidth: iconAndTextRoot.vertical ? minimumIconSize : implicitMinimumIconSize + Layout.minimumHeight: iconAndTextRoot.vertical ? implicitMinimumIconSize : minimumIconSize + } + + Item { + id: text + + // Otherwise it takes up too much space while loading + visible: label.text.length > 0 + + Layout.fillWidth: iconAndTextRoot.vertical + Layout.fillHeight: !iconAndTextRoot.vertical + Layout.minimumWidth: iconAndTextRoot.vertical ? 0 : sizehelper.paintedWidth + Layout.maximumWidth: iconAndTextRoot.vertical ? Infinity : Layout.minimumWidth + + Layout.minimumHeight: iconAndTextRoot.vertical ? sizehelper.paintedHeight : 0 + Layout.maximumHeight: iconAndTextRoot.vertical ? Layout.minimumHeight : Infinity + + Text { + id: sizehelper + + font { + family: label.font.family + weight: label.font.weight + italic: label.font.italic + pixelSize: iconAndTextRoot.vertical ? Kirigami.Units.gridUnit * 2 : 1024 // random "big enough" size - this is used as a max pixelSize by the fontSizeMode + } + minimumPixelSize: Math.round(Kirigami.Units.gridUnit / 2) + fontSizeMode: iconAndTextRoot.vertical ? Text.HorizontalFit : Text.VerticalFit + wrapMode: Text.NoWrap + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + anchors { + leftMargin: Kirigami.Units.smallSpacing + rightMargin: Kirigami.Units.smallSpacing + } + // These magic values are taken from the digital clock, so that the + // text sizes here are identical with various clock text sizes + height: { + const textHeightScaleFactor = (parent.height > 26) ? 0.7 : 0.9; + return Math.min (parent.height * textHeightScaleFactor, 3 * Kirigami.Theme.defaultFont.pixelSize); + } + visible: false + + // pattern to reserve some constant space TODO: improve and take formatting/i18n into account + text: "888° X" + textFormat: Text.PlainText + } + + PlasmaComponents.Label { + id: label + + font { + weight: Font.Normal + pixelSize: 1024 + } + minimumPixelSize: Math.round(Kirigami.Units.gridUnit / 2) + fontSizeMode: Text.Fit + textFormat: Text.PlainText + wrapMode: Text.NoWrap + + height: 0 + width: 0 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors { + fill: parent + leftMargin: Kirigami.Units.smallSpacing + rightMargin: Kirigami.Units.smallSpacing + } + } + } +} diff --git a/package/contents/ui/configGeneral.qml b/package/contents/ui/configGeneral.qml index 29e34be..f93791f 100644 --- a/package/contents/ui/configGeneral.qml +++ b/package/contents/ui/configGeneral.qml @@ -5,6 +5,7 @@ import Qt.labs.settings import org.kde.kcmutils as KCM import org.kde.kirigami as Kirigami import org.kde.plasma.plasma5support as P5Support +import org.kde.plasma.plasmoid import "components" as Components KCM.SimpleKCM { @@ -18,11 +19,26 @@ KCM.SimpleKCM { property alias cfg_threshold_video: thresholdVideo.value property alias cfg_threshold_video_enhance: thresholdVideoEnhance.value property alias cfg_threshold_blitter: thresholdBlitter.value - property var cardsList: [] property string getCardsCommand: "intel_gpu_top -L" property string cardsString: "" + property bool cfg_needsToBeSquare + + readonly property bool canShowMoreInCompactMode: !cfg_needsToBeSquare + + property alias cfg_showUsageMode: showUsageModeComboBox.currentIndex + property alias cfg_badgeStyle: badgeStyleComboBox.currentIndex + property alias cfg_usageSource: usageSourceComboBox.currentIndex + + property var showUsageModes: { + let modes = ["Disable", "Badge"] + if (canShowMoreInCompactMode) { + modes.push("Beside icon") + } + return modes + } + P5Support.DataSource { id: getCards @@ -184,5 +200,29 @@ KCM.SimpleKCM { from: 0 to: 100 } + + Kirigami.Separator { + Kirigami.FormData.label: i18n("Appearance") + Kirigami.FormData.isSection: true + } + + ComboBox { + Kirigami.FormData.label: i18n("Show usage:") + id: showUsageModeComboBox + model: showUsageModes + } + + ComboBox { + Kirigami.FormData.label: i18n("Badge style:") + id: badgeStyleComboBox + model: ["Percentage", "Color circle"] + visible: cfg_showUsageMode === 1 + } + + ComboBox { + Kirigami.FormData.label: i18n("Usage source:") + id: usageSourceComboBox + model: ["Current engine", "Total (RC6)"] + } } } diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 7bbf5da..cadc56a 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -16,6 +16,9 @@ PlasmoidItem { height: Kirigami.Units.gridUnit * 4 property var usageNow: Globals.baseStats property var usageLast: Globals.baseStats + property int usageSource: plasmoid.configuration.usageSource + property var currentEngineUsage + property var currentUsage: usageSource === 0 ? currentEngineUsage : 100 - usageNow.rc6.value property var clients3d: [] property var clientsVideo: [] property var clientsVideoEnhance: [] @@ -34,10 +37,24 @@ PlasmoidItem { property int thresholdBlitter: plasmoid.configuration.threshold_blitter property string commandEerror: "" + Plasmoid.icon: Qt.resolvedUrl("../icons/" + engineIcon).toString().replace("file://", "") + + property bool needsToBeSquare: (Plasmoid.containmentType & PlasmaCore.Types.CustomEmbeddedContainment) + | (Plasmoid.containmentDisplayHints & PlasmaCore.Types.ContainmentForcesSquarePlasmoids) + + onNeedsToBeSquareChanged: { + Qt.callLater(function() { + if (plasmoid.configuration.needsToBeSquare !== needsToBeSquare) { + plasmoid.configuration.needsToBeSquare = needsToBeSquare + plasmoid.configuration.writeConfig(); + } + }) + } + compactRepresentation: CompactRepresentation { engineIcon: main.engineIcon badgeColor: main.badgeColor - usageNow: main.usageNow + currentUsage: main.currentUsage } toolTipItem: Tooltip { @@ -110,6 +127,7 @@ PlasmoidItem { var activeEngine = Utils.getActiveEngineIcon(usageNow, threshold3d, thresholdVideo, thresholdVideoEnhance, thresholdBlitter) engineIcon = activeEngine.icon badgeColor = activeEngine.color + currentEngineUsage = activeEngine.busy } }