From 086c5c9f0239b230d75c8365da0ab365bafaf0c1 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sun, 18 May 2025 00:23:21 +0800 Subject: feat: dashboard user --- config/DashboardConfig.qml | 3 + modules/dashboard/Dash.qml | 10 ++-- modules/dashboard/dash/User.qml | 122 ++++++++++++++++++++++++++++++++++++++++ utils/Icons.qml | 23 +++++--- 4 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 modules/dashboard/dash/User.qml diff --git a/config/DashboardConfig.qml b/config/DashboardConfig.qml index a0b2106..b24232a 100644 --- a/config/DashboardConfig.qml +++ b/config/DashboardConfig.qml @@ -9,5 +9,8 @@ Singleton { component Sizes: QtObject { readonly property int tabIndicatorHeight: 3 readonly property int tabIndicatorSpacing: 5 + readonly property int faceSize: 100 + readonly property int infoWidth: 200 + readonly property int infoIconSize: 25 } } diff --git a/modules/dashboard/Dash.qml b/modules/dashboard/Dash.qml index 66af8cb..1631287 100644 --- a/modules/dashboard/Dash.qml +++ b/modules/dashboard/Dash.qml @@ -1,7 +1,7 @@ import "root:/widgets" import "root:/services" import "root:/config" -import Quickshell +import "dash" import QtQuick.Layouts GridLayout { @@ -11,11 +11,9 @@ GridLayout { columnSpacing: Appearance.spacing.small Rect { - text: "user" - Layout.columnSpan: 3 - Layout.preferredWidth: 300 - Layout.preferredHeight: 150 + + User {} } Rect { @@ -65,7 +63,7 @@ GridLayout { } component Rect: StyledRect { - required property string text + property string text radius: Appearance.rounding.small color: Colours.palette.m3surfaceContainer diff --git a/modules/dashboard/dash/User.qml b/modules/dashboard/dash/User.qml new file mode 100644 index 0000000..f8acdfd --- /dev/null +++ b/modules/dashboard/dash/User.qml @@ -0,0 +1,122 @@ +import "root:/widgets" +import "root:/services" +import "root:/config" +import "root:/utils" +import Quickshell +import Quickshell.Io +import Quickshell.Widgets +import QtQuick +import Qt.labs.platform + +Row { + id: root + + padding: Appearance.padding.large + spacing: Appearance.spacing.large + + ClippingRectangle { + implicitWidth: DashboardConfig.sizes.faceSize + implicitHeight: DashboardConfig.sizes.faceSize + + radius: Appearance.rounding.full + color: Colours.palette.m3surfaceContainerHigh + + MaterialIcon { + anchors.centerIn: parent + + text: "person" + font.pointSize: DashboardConfig.sizes.faceSize / 2 + } + + CachingImage { + anchors.fill: parent + path: `${StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]}/.face` + } + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + } + + Column { + spacing: Appearance.spacing.normal + + InfoLine { + icon: Icons.osIcon + text: Icons.osName + colour: Colours.palette.m3primary + } + + InfoLine { + icon: "select_window_2" + text: Quickshell.env("XDG_CURRENT_DESKTOP") || Quickshell.env("XDG_SESSION_DESKTOP") + colour: Colours.palette.m3secondary + } + + InfoLine { + icon: "timer" + text: uptimeProc.uptime + colour: Colours.palette.m3tertiary + + Timer { + running: true + repeat: true + interval: 15000 + onTriggered: uptimeProc.running = true + } + + Process { + id: uptimeProc + + property string uptime + + running: true + command: ["uptime", "-p"] + stdout: SplitParser { + onRead: data => uptimeProc.uptime = data + } + } + } + } + + component InfoLine: Item { + id: line + + required property string icon + required property string text + required property color colour + + implicitWidth: icon.implicitWidth + text.width + text.anchors.leftMargin + implicitHeight: Math.max(icon.implicitHeight, text.implicitHeight) + + MaterialIcon { + id: icon + + anchors.left: parent.left + anchors.leftMargin: (DashboardConfig.sizes.infoIconSize - implicitWidth) / 2 + + text: line.icon + color: line.colour + font.pointSize: Appearance.font.size.normal + font.variableAxes: ({ + FILL: 1 + }) + } + + AnchorText { + id: text + + prevAnchor: icon + anchors.leftMargin: icon.anchors.leftMargin + text: `: ${line.text}` + font.pointSize: Appearance.font.size.normal + + width: DashboardConfig.sizes.infoWidth + elide: Text.ElideRight + } + } +} diff --git a/utils/Icons.qml b/utils/Icons.qml index 312ae6d..504cdc5 100644 --- a/utils/Icons.qml +++ b/utils/Icons.qml @@ -151,6 +151,7 @@ Singleton { }) property string osIcon: "" + property string osName function getAppCategoryIcon(name: string, fallback: string): string { const categories = DesktopEntries.applications.values.find(app => app.id === name)?.categories; @@ -187,14 +188,22 @@ Singleton { FileView { path: "/etc/os-release" onLoaded: { - const osId = this.text().split("\n").find(l => l.startsWith("ID="))?.split("=")[1]; + const lines = text().split("\n"); + let osId = lines.find(l => l.startsWith("ID="))?.split("=")[1]; if (root.osIcons.hasOwnProperty(osId)) - return root.osIcon = root.osIcons[osId]; - const osIdLike = this.text().split("\n").find(l => l.startsWith("ID_LIKE="))?.split("=")[1]; - if (osIdLike) - for (const id of osIdLike.split(" ")) - if (root.osIcons.hasOwnProperty(id)) - return root.osIcon = root.osIcons[id]; + root.osIcon = root.osIcons[osId]; + else { + const osIdLike = lines.find(l => l.startsWith("ID_LIKE="))?.split("=")[1]; + if (osIdLike) + for (const id of osIdLike.split(" ")) + if (root.osIcons.hasOwnProperty(id)) + return root.osIcon = root.osIcons[id]; + } + + let nameLine = lines.find(l => l.startsWith("PRETTY_NAME=")); + if (!nameLine) + nameLine = lines.find(l => l.startsWith("NAME=")); + root.osName = nameLine.split("=")[1].slice(1, -1); } } } -- cgit v1.2.3-freya