Tons of small changes, add SidePanel, NCard, NCircleStat, NSystemMnitor

This commit is contained in:
Ly-sec 2025-08-10 19:25:44 +02:00
parent b0ff67e2e4
commit 92e121b356
12 changed files with 579 additions and 5 deletions

View file

@ -73,8 +73,28 @@ NLoader {
// NSlider
ColumnLayout {
spacing: 16 * scaling
NText { text: "NSlider"; color: Colors.accentSecondary }
NSlider {}
NText { text: "Scaling"; color: Colors.accentSecondary }
RowLayout {
spacing: Style.marginSmall * scaling
NText { text: `${Math.round(Scaling.overrideScale * 100)}%`; Layout.alignment: Qt.AlignVCenter }
NSlider {
id: scaleSlider
from: 0.6
to: 1.8
stepSize: 0.01
value: Scaling.overrideScale
onMoved: function() { Scaling.overrideScale = value }
onPressedChanged: function() { Scaling.overrideEnabled = true }
}
NIconButton {
icon: "restart_alt"
sizeMultiplier: 0.7
onClicked: function() {
Scaling.overrideEnabled = false
Scaling.overrideScale = 1.0
}
}
}
NDivider { Layout.fillWidth: true }
}
}

View file

@ -0,0 +1,44 @@
import QtQuick
import QtQuick.Layouts
import qs.Services
import qs.Widgets
// Media player area (placeholder until MediaPlayer service is wired)
NBox {
id: root
readonly property real scaling: Scaling.scale(screen)
Layout.fillWidth: true
// Let content dictate the height (no hardcoded height here)
// Height can be overridden by parent layout (SidePanel binds it to stats card)
implicitHeight: content.implicitHeight + Style.marginLarge * 2 * scaling
Column {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Style.marginXL * scaling
spacing: Style.marginSmall * scaling
Item { height: 36 * scaling }
Text {
text: "music_note"
font.family: "Material Symbols Outlined"
font.pointSize: 28 * scaling
color: Colors.textSecondary
anchors.horizontalCenter: parent.horizontalCenter
}
NText {
text: "No music player detected"
color: Colors.textSecondary
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
}
Item { height: 36 * scaling }
}
}

View file

@ -0,0 +1,68 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import QtQuick.Effects
import qs.Services
import qs.Widgets
// Header card with avatar, user and quick actions
NBox {
id: root
readonly property real scaling: Scaling.scale(screen)
Layout.fillWidth: true
// Height driven by content
implicitHeight: content.implicitHeight + Style.marginMedium * 2 * scaling
RowLayout {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Style.marginMedium * scaling
spacing: Style.marginMedium * scaling
Item {
id: avatarBox
width: 40 * scaling
height: 40 * scaling
Image {
id: avatarImage
anchors.fill: parent
source: Settings.data.general.avatarImage
fillMode: Image.PreserveAspectCrop
asynchronous: true
}
// Ensure rounded corners consistently across renderers
MultiEffect {
anchors.fill: avatarImage
source: avatarImage
maskEnabled: true
maskSource: Rectangle {
anchors.fill: parent
color: "white"
radius: Style.radiusMedium * scaling
}
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 2 * scaling
NText { text: Quickshell.env("USER") || "user" }
NText { text: "System Uptime: —"; color: Colors.textSecondary }
}
RowLayout {
spacing: Style.marginSmall * scaling
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Item { Layout.fillWidth: true }
NIconButton { icon: "settings"; sizeMultiplier: 0.8 }
NIconButton { icon: "power_settings_new"; sizeMultiplier: 0.8 }
}
}
}

View file

@ -6,6 +6,7 @@ import Quickshell.Wayland
import qs.Services
import qs.Widgets
NLoader {
id: root
@ -34,6 +35,8 @@ NLoader {
id: sidePanel
readonly property real scaling: Scaling.scale(screen)
// Single source of truth for spacing between cards (both axes)
property real cardSpacing: Style.marginLarge * scaling
// X coordinate from the bar to align this panel under
property real anchorX: root.anchorX
// Ensure this panel attaches to the intended screen
@ -42,13 +45,19 @@ NLoader {
// Ensure panel shows itself once created
Component.onCompleted: show()
// Inline helpers moved to dedicated widgets: NCard and NCircleStat
Rectangle {
id: panelBackground
color: Colors.backgroundPrimary
radius: Style.radiusLarge * scaling
border.color: Colors.backgroundTertiary
border.width: Math.min(1, Style.borderMedium * scaling)
width: 500 * scaling
height: 400
layer.enabled: true
width: 460 * scaling
property real innerMargin: sidePanel.cardSpacing
// Height scales to content plus vertical padding
height: content.implicitHeight + innerMargin * 2
// Place the panel just below the bar (overlay content starts below bar due to topMargin)
y: Style.marginSmall * scaling
// Center horizontally under the anchorX, clamped to the screen bounds
@ -60,6 +69,103 @@ NLoader {
// Prevent closing when clicking in the panel bg
MouseArea { anchors.fill: parent }
// Content wrapper to ensure childrenRect drives implicit height
Item {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: panelBackground.innerMargin
implicitHeight: layout.implicitHeight
// Layout content (not vertically anchored so implicitHeight is valid)
ColumnLayout {
id: layout
// Use the same spacing value horizontally and vertically
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
spacing: sidePanel.cardSpacing
// Cards (consistent inter-card spacing via ColumnLayout spacing)
ProfileCard { Layout.topMargin: 0; Layout.bottomMargin: 0 }
WeatherCard { Layout.topMargin: 0; Layout.bottomMargin: 0 }
// Middle section: media + stats column
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 0
Layout.bottomMargin: 0
spacing: sidePanel.cardSpacing
// Media card
MediaCard { id: mediaCard; Layout.fillWidth: true; implicitHeight: statsCard.implicitHeight }
// System monitors combined in one card
SystemCard { id: statsCard }
}
// Bottom actions (two grouped rows of round buttons)
RowLayout {
Layout.fillWidth: true
Layout.topMargin: 0
Layout.bottomMargin: 0
spacing: sidePanel.cardSpacing
// Power Profiles: performance, balanced, eco
NBox {
Layout.fillWidth: true
Layout.preferredWidth: 1
implicitHeight: powerRow.implicitHeight + Style.marginSmall * 2 * scaling
RowLayout {
id: powerRow
anchors.fill: parent
anchors.margins: Style.marginSmall * scaling
spacing: sidePanel.cardSpacing
Item { Layout.fillWidth: true }
// Performance
NIconButton {
icon: "speed"
sizeMultiplier: 1.0
onClicked: function () { /* TODO: hook to power profile */ }
}
// Balanced
NIconButton {
icon: "balance"
sizeMultiplier: 1.0
onClicked: function () { /* TODO: hook to power profile */ }
}
// Eco
NIconButton {
icon: "eco"
sizeMultiplier: 1.0
onClicked: function () { /* TODO: hook to power profile */ }
}
Item { Layout.fillWidth: true }
}
}
// Utilities: record & wallpaper
NBox {
Layout.fillWidth: true
Layout.preferredWidth: 1
implicitHeight: utilRow.implicitHeight + Style.marginSmall * 2 * scaling
RowLayout {
id: utilRow
anchors.fill: parent
anchors.margins: Style.marginSmall * scaling
spacing: sidePanel.cardSpacing
Item { Layout.fillWidth: true }
// Record
NIconButton { icon: "fiber_manual_record"; sizeMultiplier: 1.0 }
// Wallpaper
NIconButton { icon: "image"; sizeMultiplier: 1.0 }
Item { Layout.fillWidth: true }
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,40 @@
import QtQuick
import QtQuick.Layouts
import qs.Services
import qs.Widgets
// Unified system card: monitors CPU, temp, memory, disk
NBox {
id: root
readonly property real scaling: Scaling.scale(screen)
Layout.preferredWidth: 84 * scaling
implicitHeight: content.implicitHeight + Style.marginTiny * 2 * scaling
Column {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: Style.marginSmall * scaling
anchors.rightMargin: Style.marginSmall * scaling
anchors.topMargin: Style.marginTiny * scaling
anchors.bottomMargin: Style.marginMedium * scaling
spacing: Style.marginSmall * scaling
// Slight top padding
Item { height: Style.marginTiny * scaling }
NSystemMonitor { id: sysMon; intervalSeconds: 1 }
NCircleStat { value: sysMon.cpuUsage || SysInfo.cpuUsage; icon: "speed"; flat: true; contentScale: 0.8; width: 72 * scaling; height: 68 * scaling }
NCircleStat { value: sysMon.cpuTemp || SysInfo.cpuTemp; suffix: "°C"; icon: "device_thermostat"; flat: true; contentScale: 0.8; width: 72 * scaling; height: 68 * scaling }
NCircleStat { value: sysMon.memoryUsagePer || SysInfo.memoryUsagePer; icon: "memory"; flat: true; contentScale: 0.8; width: 72 * scaling; height: 68 * scaling }
NCircleStat { value: sysMon.diskUsage || SysInfo.diskUsage; icon: "data_usage"; flat: true; contentScale: 0.8; width: 72 * scaling; height: 68 * scaling }
// Extra bottom padding to shift the perceived stack slightly upward
Item { height: Style.marginMedium * scaling }
}
}

View file

@ -0,0 +1,59 @@
import QtQuick
import QtQuick.Layouts
import qs.Services
import qs.Widgets
// Weather overview card (placeholder data)
NBox {
id: root
readonly property real scaling: Scaling.scale(screen)
Layout.fillWidth: true
// Height driven by content
implicitHeight: content.implicitHeight + Style.marginLarge * 2 * scaling
ColumnLayout {
id: content
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: Style.marginLarge * scaling
spacing: Style.marginSmall * scaling
RowLayout {
spacing: Style.marginSmall * scaling
Text {
text: "sunny"
font.family: "Material Symbols Outlined"
font.pointSize: Style.fontSizeXL * scaling
color: Colors.accentSecondary
}
ColumnLayout {
NText { text: "Dinslaken (GMT+2)" }
NText { text: "26°C"; font.pointSize: (Style.fontSizeXL + 6) * scaling }
}
}
Rectangle { height: 1; width: parent.width; color: Colors.backgroundTertiary }
RowLayout {
Layout.fillWidth: true
spacing: Style.marginLarge * scaling
Repeater {
model: 5
delegate: ColumnLayout {
spacing: 2 * scaling
NText { text: ["Sun","Mon","Tue","Wed","Thu"][index] }
Text {
text: index % 2 === 0 ? "wb_sunny" : "cloud"
font.family: "Material Symbols Outlined"
color: Colors.textSecondary
}
NText { text: "26° / 14°"; color: Colors.textSecondary }
}
}
}
}
}