nova-shell/modules/Memory.qml

299 lines
9 KiB
QML

import QtQuick
import "." as M
M.BarSection {
id: root
spacing: Math.max(1, M.Theme.moduleSpacing - 2)
tooltip: ""
property int percent: M.SystemStats.memPercent
property real usedGb: M.SystemStats.memUsedGb
property real totalGb: M.SystemStats.memTotalGb
property real availGb: M.SystemStats.memAvailGb
property real cachedGb: M.SystemStats.memCachedGb
property real buffersGb: M.SystemStats.memBuffersGb
function _fmt(gb) {
return gb >= 10 ? gb.toFixed(1) + "G" : gb.toFixed(2) + "G";
}
property bool _pinned: false
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
readonly property bool _showPanel: _anyHover || _pinned
property M.ProcessList _procs: M.ProcessList {
sortBy: "mem"
active: root._showPanel
}
on_AnyHoverChanged: {
if (_anyHover)
_unpinTimer.stop();
else if (_pinned)
_unpinTimer.start();
}
Timer {
id: _unpinTimer
interval: 500
onTriggered: root._pinned = false
}
M.BarIcon {
icon: "\uEFC5"
anchors.verticalCenter: parent.verticalCenter
TapHandler {
cursorShape: Qt.PointingHandCursor
onTapped: root._pinned = !root._pinned
}
}
M.BarLabel {
label: root.percent + "%"
minText: "100%"
anchors.verticalCenter: parent.verticalCenter
TapHandler {
cursorShape: Qt.PointingHandCursor
onTapped: root._pinned = !root._pinned
}
}
M.HoverPanel {
id: hoverPanel
showPanel: root._showPanel
screen: QsWindow.window?.screen ?? null
anchorItem: root
accentColor: root.accentColor
panelNamespace: "nova-memory"
contentWidth: 240
// Header
Item {
width: parent.width
height: 28
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Memory"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 1
font.family: M.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root._fmt(root.usedGb) + " / " + root._fmt(root.totalGb)
color: root.accentColor
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
font.bold: true
}
}
// Usage bar
Item {
width: parent.width
height: 14
Item {
id: memBar
anchors.left: parent.left
anchors.leftMargin: 12
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
height: 6
Rectangle {
anchors.fill: parent
color: M.Theme.base02
radius: 3
}
// Cached (base0D, behind used)
Rectangle {
width: parent.width * Math.min(1, (root.usedGb + root.cachedGb) / Math.max(root.totalGb, 0.001))
height: parent.height
color: M.Theme.base0D
opacity: 0.4
radius: 3
Behavior on width {
enabled: root._showPanel
NumberAnimation {
duration: 200
}
}
}
// Used (accentColor, on top)
Rectangle {
width: parent.width * Math.min(1, root.usedGb / Math.max(root.totalGb, 0.001))
height: parent.height
color: root.accentColor
radius: 3
Behavior on width {
enabled: root._showPanel
NumberAnimation {
duration: 200
}
}
}
}
}
// Breakdown rows
Item {
width: parent.width
height: 18
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Used"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root._fmt(root.usedGb)
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
}
}
Item {
width: parent.width
height: 18
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Cached"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root._fmt(root.cachedGb)
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
}
}
Item {
width: parent.width
height: 18
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Available"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root._fmt(root.availGb)
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
}
}
// Process list separator
Rectangle {
width: parent.width - 16
height: 1
anchors.horizontalCenter: parent.horizontalCenter
color: M.Theme.base03
}
Item {
width: hoverPanel.contentWidth
height: 18
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "PROCESS"
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 3
font.family: M.Theme.fontFamily
font.letterSpacing: 1
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "MEM"
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 3
font.family: M.Theme.fontFamily
font.letterSpacing: 1
}
}
// Top processes by memory
Repeater {
model: root._procs.processes
delegate: Item {
required property var modelData
width: hoverPanel.contentWidth
height: 20
Text {
id: procCmd
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: modelData.cmd
color: M.Theme.base05
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
elide: Text.ElideRight
width: parent.width - 80
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: modelData.mem.toFixed(1) + "%"
color: M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
width: 36
horizontalAlignment: Text.AlignRight
}
}
}
Item {
width: 1
height: 4
}
}
}