feat: initial commit for pixel-snapping components and helpers
This commit is contained in:
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import ZShell.Config
|
||||
import ZShell
|
||||
import qs.Components
|
||||
@@ -39,8 +40,8 @@ Item {
|
||||
];
|
||||
return allTabs.filter(tab => tab.enabled);
|
||||
}
|
||||
readonly property real nonAnimHeight: tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins + viewWrapper.anchors.topMargin
|
||||
readonly property real nonAnimWidth: view.implicitWidth + viewWrapper.anchors.margins * 2
|
||||
readonly property real nonAnimHeight: ZUtils.snap(tabs.implicitHeight + tabs.anchors.topMargin + view.implicitHeight + viewWrapper.anchors.margins + viewWrapper.anchors.topMargin, root)
|
||||
readonly property real nonAnimWidth: ZUtils.snap(view.implicitWidth + viewWrapper.anchors.margins * 2, root)
|
||||
required property ScreenState screenState
|
||||
|
||||
implicitHeight: nonAnimHeight
|
||||
@@ -93,8 +94,8 @@ Item {
|
||||
}
|
||||
|
||||
anchors.fill: parent
|
||||
implicitHeight: currentItem?.implicitHeight ?? 0
|
||||
implicitWidth: currentItem?.implicitWidth ?? 0
|
||||
implicitHeight: currentItem?.height ?? currentItem?.implicitHeight ?? 0
|
||||
implicitWidth: currentItem?.width ?? currentItem?.implicitWidth ?? 0
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
|
||||
+55
-77
@@ -1,104 +1,82 @@
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell
|
||||
import ZShell.Config
|
||||
import ZShell.Components
|
||||
import qs.Helpers
|
||||
import qs.Components
|
||||
import qs.Modules
|
||||
import ZShell.Config
|
||||
import qs.Modules.Dashboard.Dash
|
||||
import qs.Services
|
||||
|
||||
GridLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: root
|
||||
|
||||
readonly property bool dashboardVisible: screenState.dashboard
|
||||
required property int radius
|
||||
required property ScreenState screenState
|
||||
|
||||
columnSpacing: Tokens.spacing.small
|
||||
rowSpacing: Tokens.spacing.small
|
||||
spacing: ZUtils.snap(Tokens.spacing.small, root)
|
||||
|
||||
ParallelAnimation {
|
||||
id: openAnim
|
||||
height: ZUtils.snap(implicitHeight, root)
|
||||
width: ZUtils.snap(implicitWidth, root)
|
||||
|
||||
Anim {
|
||||
property: "opacity"
|
||||
target: root
|
||||
to: 1
|
||||
}
|
||||
|
||||
Anim {
|
||||
property: "scale"
|
||||
target: root
|
||||
to: 1
|
||||
}
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: closeAnim
|
||||
|
||||
Anim {
|
||||
property: "opacity"
|
||||
target: root
|
||||
to: 0
|
||||
}
|
||||
|
||||
Anim {
|
||||
property: "scale"
|
||||
target: root
|
||||
to: 0.9
|
||||
}
|
||||
}
|
||||
|
||||
Rect {
|
||||
Layout.column: 2
|
||||
Layout.columnSpan: 3
|
||||
Layout.preferredHeight: user.implicitHeight
|
||||
Layout.preferredWidth: user.implicitWidth
|
||||
radius: root.radius
|
||||
|
||||
User {
|
||||
id: user
|
||||
|
||||
screenState: root.screenState
|
||||
}
|
||||
}
|
||||
|
||||
Rect {
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: Tokens.sizes.dashboard.weatherWidth
|
||||
Layout.row: 0
|
||||
radius: root.radius
|
||||
|
||||
Weather {}
|
||||
}
|
||||
|
||||
Rect {
|
||||
Layout.column: 0
|
||||
Layout.columnSpan: 3
|
||||
SnapLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: calendar.implicitHeight
|
||||
Layout.row: 1
|
||||
radius: root.radius
|
||||
spacing: parent.spacing
|
||||
|
||||
Calendar {
|
||||
id: calendar
|
||||
Rect {
|
||||
id: weatherRect
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: ZUtils.snap(Tokens.sizes.dashboard.weatherWidth, root)
|
||||
radius: root.radius
|
||||
|
||||
screenState: root.screenState
|
||||
Weather {}
|
||||
}
|
||||
|
||||
Rect {
|
||||
id: userRect
|
||||
Layout.preferredHeight: ZUtils.snap(user.implicitHeight, root)
|
||||
Layout.preferredWidth: ZUtils.snap(user.implicitWidth, root)
|
||||
radius: root.radius
|
||||
|
||||
User {
|
||||
id: user
|
||||
|
||||
screenState: root.screenState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rect {
|
||||
Layout.column: 3
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: resources.implicitWidth
|
||||
Layout.row: 1
|
||||
radius: root.radius
|
||||
SnapLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: parent.spacing
|
||||
|
||||
Resources {
|
||||
id: resources
|
||||
Rect {
|
||||
id: calendarRect
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
implicitHeight: ZUtils.snap(calendar.implicitHeight, root)
|
||||
radius: root.radius
|
||||
|
||||
Calendar {
|
||||
id: calendar
|
||||
|
||||
screenState: root.screenState
|
||||
}
|
||||
}
|
||||
|
||||
Rect {
|
||||
id: resourcesRect
|
||||
Layout.fillHeight: true
|
||||
implicitWidth: ZUtils.snap(resources.implicitWidth, root)
|
||||
radius: root.radius
|
||||
|
||||
Resources {
|
||||
id: resources
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import Quickshell
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import qs.Components
|
||||
import ZShell.Config
|
||||
import qs.Services
|
||||
@@ -117,14 +118,15 @@ CustomMouseArea {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: inner
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Tokens.padding.large
|
||||
spacing: Tokens.spacing.extraSmall
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
id: monthNavigationRow
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import ZShell
|
||||
import ZShell.Services
|
||||
import ZShell.Config
|
||||
import qs.Components
|
||||
@@ -8,9 +10,8 @@ import qs.Services
|
||||
Item {
|
||||
id: root
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
implicitWidth: layout.implicitWidth + layout.anchors.margins * 4
|
||||
anchors.fill: parent
|
||||
implicitWidth: ZUtils.snap(layout.implicitWidth + layout.anchors.margins * 2, root)
|
||||
|
||||
ServiceRef {
|
||||
service: Storage
|
||||
@@ -28,13 +29,16 @@ Item {
|
||||
service: Gpu
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: layout
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.margins: Tokens.padding.large
|
||||
anchors.top: parent.top
|
||||
|
||||
x: ZUtils.snap((root.width - implicitWidth) / 2, root)
|
||||
|
||||
spacing: Tokens.spacing.medium
|
||||
|
||||
Resource {
|
||||
@@ -73,12 +77,10 @@ Item {
|
||||
|
||||
required property string icon
|
||||
|
||||
Layout.fillHeight: true
|
||||
implicitSize: height
|
||||
implicitSize: ZUtils.snap((root.height - layout.anchors.margins * 2 - layout.spacing * 4) / 5, root)
|
||||
|
||||
Behavior on clampedVal {
|
||||
Anim {
|
||||
}
|
||||
Anim {}
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import M3Shapes
|
||||
import ZShell
|
||||
import ZShell.Config
|
||||
import qs.Modules.Dashboard.Media
|
||||
import qs.Components
|
||||
@@ -13,8 +15,8 @@ Item {
|
||||
property ScreenState screenState
|
||||
required property int radius
|
||||
|
||||
implicitWidth: 1000
|
||||
implicitHeight: 320
|
||||
implicitWidth: ZUtils.snap(1000, root)
|
||||
implicitHeight: ZUtils.snap(320, root)
|
||||
|
||||
ClipRect {
|
||||
anchors.fill: parent
|
||||
@@ -25,7 +27,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Tokens.padding.large
|
||||
spacing: Tokens.spacing.extraLarge
|
||||
@@ -94,7 +96,8 @@ Item {
|
||||
active: opacity > 0
|
||||
opacity: 0
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
sourceComponent: SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
spacing: Tokens.spacing.small
|
||||
|
||||
MaterialShape {
|
||||
@@ -140,11 +143,12 @@ Item {
|
||||
asynchronous: true
|
||||
active: opacity > 0
|
||||
|
||||
sourceComponent: RowLayout {
|
||||
sourceComponent: SnapLayout {
|
||||
spacing: Tokens.spacing.extraLarge
|
||||
|
||||
Details {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
LyricsAndSelector {
|
||||
|
||||
+178
-154
@@ -1,13 +1,14 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell.Services.Mpris
|
||||
import ZShell
|
||||
import ZShell.Components
|
||||
import ZShell.Config
|
||||
import qs.Components
|
||||
import qs.Services
|
||||
import qs.Helpers
|
||||
|
||||
ColumnLayout {
|
||||
Item {
|
||||
id: root
|
||||
|
||||
readonly property bool hasUnknownLength: (Players.active?.length ?? 0) > 2147483647
|
||||
@@ -25,46 +26,187 @@ ColumnLayout {
|
||||
return `${mins}:${secs}`;
|
||||
}
|
||||
|
||||
spacing: Tokens.spacing.extraSmall
|
||||
implicitHeight: ZUtils.snap(layout.implicitHeight, root)
|
||||
implicitWidth: layout.implicitWidth
|
||||
|
||||
Timer {
|
||||
running: Players.active?.isPlaying ?? false
|
||||
interval: Config.dashboard.mediaUpdateInterval
|
||||
triggeredOnStart: true
|
||||
repeat: true
|
||||
onTriggered: Players.active?.positionChanged()
|
||||
}
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: layout
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
y: ZUtils.snap((parent.height - implicitHeight) / 2, root)
|
||||
|
||||
CustomText {
|
||||
Layout.fillWidth: true
|
||||
text: Players.active?.trackTitle ?? ""
|
||||
font: Tokens.font.title.large
|
||||
elide: Text.ElideRight
|
||||
animate: true
|
||||
}
|
||||
spacing: ZUtils.snap(Tokens.spacing.extraSmall, root)
|
||||
|
||||
CustomText {
|
||||
Layout.fillWidth: true
|
||||
text: Players.active?.trackArtist || qsTr("Unknown artist")
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font: Tokens.font.title.medium
|
||||
elide: Text.ElideRight
|
||||
animate: true
|
||||
}
|
||||
Timer {
|
||||
running: Players.active?.isPlaying ?? false
|
||||
interval: Config.dashboard.mediaUpdateInterval
|
||||
triggeredOnStart: true
|
||||
repeat: true
|
||||
onTriggered: Players.active?.positionChanged()
|
||||
}
|
||||
|
||||
CustomText {
|
||||
Layout.fillWidth: true
|
||||
text: Players.active?.trackAlbum || qsTr("Unknown album")
|
||||
color: Colors.palette.m3secondary
|
||||
font: Tokens.font.title.medium
|
||||
elide: Text.ElideRight
|
||||
animate: true
|
||||
}
|
||||
CustomText {
|
||||
id: title
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: ZUtils.snapCeil(implicitHeight, root)
|
||||
text: Players.active?.trackTitle ?? ""
|
||||
font: Tokens.font.title.large
|
||||
elide: Text.ElideRight
|
||||
animate: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: Tokens.spacing.extraLargeIncreased
|
||||
Layout.fillWidth: true
|
||||
spacing: Tokens.spacing.small
|
||||
CustomText {
|
||||
id: artist
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: ZUtils.snapCeil(implicitHeight, root)
|
||||
text: Players.active?.trackArtist || qsTr("Unknown artist")
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font: Tokens.font.title.medium
|
||||
elide: Text.ElideRight
|
||||
animate: true
|
||||
}
|
||||
|
||||
CustomText {
|
||||
id: album
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: ZUtils.snapCeil(implicitHeight, root)
|
||||
text: Players.active?.trackAlbum || qsTr("Unknown album")
|
||||
color: Colors.palette.m3secondary
|
||||
font: Tokens.font.title.medium
|
||||
elide: Text.ElideRight
|
||||
animate: true
|
||||
}
|
||||
|
||||
SnapLayout {
|
||||
id: sliderLayout
|
||||
Layout.topMargin: Tokens.spacing.extraLargeIncreased
|
||||
Layout.fillWidth: true
|
||||
spacing: ZUtils.snap(Tokens.spacing.small, root)
|
||||
|
||||
CustomText {
|
||||
id: positionLabel
|
||||
|
||||
Layout.preferredWidth: ZUtils.snapCeil(timeMetrics.width, root)
|
||||
Layout.preferredHeight: positionSlider.implicitHeight
|
||||
text: root.lengthStr(Players.active?.position ?? -1)
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font: timeMetrics.font
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
CustomSlider {
|
||||
id: positionSlider
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: ZUtils.snap(implicitHeight, root)
|
||||
value: Players.active ? Players.active.position / (Players.active.length || 1) : 0
|
||||
enabled: (Players.active?.canSeek ?? false) && !root.hasUnknownLength
|
||||
wavy: true
|
||||
animateWave: Players.active?.isPlaying ?? false
|
||||
waveFrequency: 5
|
||||
waveDuration: 2000
|
||||
interactionOnMove: false
|
||||
onInteraction: value => {
|
||||
const active = Players.active;
|
||||
if (active?.canSeek && active?.positionSupported)
|
||||
active.position = value * active.length;
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: positionLabel
|
||||
property: "text"
|
||||
value: root.lengthStr(positionSlider.pos * (Players.active?.length ?? 0))
|
||||
when: positionSlider.dragging
|
||||
}
|
||||
}
|
||||
|
||||
CustomText {
|
||||
Layout.preferredWidth: ZUtils.snapCeil(timeMetrics.width, root)
|
||||
Layout.preferredHeight: positionSlider.implicitHeight
|
||||
text: root.hasUnknownLength ? "--:--" : root.lengthStr(Players.active?.length ?? -1)
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font: timeMetrics.font
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
ButtonRow {
|
||||
Layout.topMargin: Tokens.spacing.largeIncreased
|
||||
Layout.fillWidth: true
|
||||
spacing: Tokens.spacing.extraSmall
|
||||
|
||||
IconButton {
|
||||
type: IconButton.Tonal
|
||||
icon: "shuffle"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
checked: Players.active?.shuffle ?? false
|
||||
font: Tokens.font.icon.builders.medium.weight(Font.Medium).build()
|
||||
enabled: Players.active?.shuffleSupported
|
||||
onClicked: Players.active.shuffle = !Players.active?.shuffle
|
||||
implicitWidth: Math.round(implicitHeight * 0.9)
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: previousBtn
|
||||
|
||||
type: IconButton.Tonal
|
||||
icon: "skip_previous"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
font: Tokens.font.icon.large
|
||||
enabled: Players.active?.canGoPrevious
|
||||
onClicked: Players.active?.previous()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: playPauseBtn
|
||||
|
||||
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
fillWidth: true
|
||||
checked: Players.active?.isPlaying ?? false
|
||||
font: Tokens.font.icon.large
|
||||
enabled: Players.active?.canTogglePlaying
|
||||
onClicked: Players.active?.togglePlaying()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: nextBtn
|
||||
|
||||
type: IconButton.Tonal
|
||||
icon: "skip_next"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
font: Tokens.font.icon.large
|
||||
enabled: Players.active?.canGoNext
|
||||
onClicked: Players.active?.next()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
type: IconButton.Tonal
|
||||
icon: Players.active?.loopState === MprisLoopState.Track ? "repeat_one" : "repeat"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
checked: Players.active?.loopState === MprisLoopState.Track || Players.active?.loopState === MprisLoopState.Playlist
|
||||
font: Tokens.font.icon.builders.medium.weight(Font.Medium).build()
|
||||
enabled: Players.active?.loopSupported
|
||||
onClicked: {
|
||||
const state = Players.active.loopState;
|
||||
if (state === MprisLoopState.None)
|
||||
Players.active.loopState = MprisLoopState.Track;
|
||||
else if (state === MprisLoopState.Track)
|
||||
Players.active.loopState = MprisLoopState.Playlist;
|
||||
else
|
||||
Players.active.loopState = MprisLoopState.None;
|
||||
}
|
||||
implicitWidth: Math.round(implicitHeight * 0.9)
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: timeMetrics
|
||||
@@ -72,123 +214,5 @@ ColumnLayout {
|
||||
text: Players.active ? root.lengthStr(Math.max(Players.active.position, root.hasUnknownLength ? 0 : Players.active.length)).replace(/[1-9]/g, "0") : "00:00"
|
||||
font: Tokens.font.label.medium
|
||||
}
|
||||
|
||||
CustomText {
|
||||
id: positionLabel
|
||||
|
||||
Layout.preferredWidth: timeMetrics.width
|
||||
text: root.lengthStr(Players.active?.position ?? -1)
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font: timeMetrics.font
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
CustomSlider {
|
||||
id: positionSlider
|
||||
|
||||
Layout.fillWidth: true
|
||||
value: Players.active ? Players.active.position / (Players.active.length || 1) : 0
|
||||
enabled: (Players.active?.canSeek ?? false) && !root.hasUnknownLength
|
||||
wavy: true
|
||||
animateWave: Players.active?.isPlaying ?? false
|
||||
waveFrequency: 5
|
||||
waveDuration: 2000
|
||||
interactionOnMove: false
|
||||
onInteraction: value => {
|
||||
const active = Players.active;
|
||||
if (active?.canSeek && active?.positionSupported)
|
||||
active.position = value * active.length;
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: positionLabel
|
||||
property: "text"
|
||||
value: root.lengthStr(positionSlider.pos * (Players.active?.length ?? 0))
|
||||
when: positionSlider.dragging
|
||||
}
|
||||
}
|
||||
|
||||
CustomText {
|
||||
Layout.preferredWidth: timeMetrics.width
|
||||
text: root.hasUnknownLength ? "--:--" : root.lengthStr(Players.active?.length ?? -1)
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font: timeMetrics.font
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
ButtonRow {
|
||||
Layout.topMargin: Tokens.spacing.largeIncreased
|
||||
Layout.fillWidth: true
|
||||
spacing: Tokens.spacing.extraSmall
|
||||
|
||||
IconButton {
|
||||
type: IconButton.Tonal
|
||||
icon: "shuffle"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
checked: Players.active?.shuffle ?? false
|
||||
font: Tokens.font.icon.builders.medium.weight(Font.Medium).build()
|
||||
enabled: Players.active?.shuffleSupported
|
||||
onClicked: Players.active.shuffle = !Players.active?.shuffle
|
||||
implicitWidth: Math.round(implicitHeight * 0.9)
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: previousBtn
|
||||
|
||||
type: IconButton.Tonal
|
||||
icon: "skip_previous"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
font: Tokens.font.icon.large
|
||||
enabled: Players.active?.canGoPrevious
|
||||
onClicked: Players.active?.previous()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: playPauseBtn
|
||||
|
||||
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
fillWidth: true
|
||||
checked: Players.active?.isPlaying ?? false
|
||||
font: Tokens.font.icon.large
|
||||
enabled: Players.active?.canTogglePlaying
|
||||
onClicked: Players.active?.togglePlaying()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: nextBtn
|
||||
|
||||
type: IconButton.Tonal
|
||||
icon: "skip_next"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
font: Tokens.font.icon.large
|
||||
enabled: Players.active?.canGoNext
|
||||
onClicked: Players.active?.next()
|
||||
}
|
||||
|
||||
IconButton {
|
||||
type: IconButton.Tonal
|
||||
icon: Players.active?.loopState === MprisLoopState.Track ? "repeat_one" : "repeat"
|
||||
isRound: true
|
||||
shapeMorph: true
|
||||
checked: Players.active?.loopState === MprisLoopState.Track || Players.active?.loopState === MprisLoopState.Playlist
|
||||
font: Tokens.font.icon.builders.medium.weight(Font.Medium).build()
|
||||
enabled: Players.active?.loopSupported
|
||||
onClicked: {
|
||||
const state = Players.active.loopState;
|
||||
if (state === MprisLoopState.None)
|
||||
Players.active.loopState = MprisLoopState.Track;
|
||||
else if (state === MprisLoopState.Track)
|
||||
Players.active.loopState = MprisLoopState.Playlist;
|
||||
else
|
||||
Players.active.loopState = MprisLoopState.None;
|
||||
}
|
||||
implicitWidth: Math.round(implicitHeight * 0.9)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import ZShell.Config
|
||||
import ZShell.Services
|
||||
import qs.Components
|
||||
@@ -157,7 +158,8 @@ Item {
|
||||
active: opacity > 0
|
||||
opacity: 0
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
sourceComponent: SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
spacing: Tokens.spacing.large
|
||||
|
||||
CustomRect {
|
||||
@@ -198,7 +200,8 @@ Item {
|
||||
active: opacity > 0
|
||||
opacity: 0
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
sourceComponent: SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
spacing: Tokens.spacing.small
|
||||
|
||||
MaterialIcon {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import Quickshell
|
||||
import Quickshell.Services.Mpris
|
||||
import ZShell.Config
|
||||
@@ -8,14 +9,15 @@ import qs.Helpers
|
||||
import qs.Services
|
||||
|
||||
Item {
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: layout
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: Tokens.padding.medium
|
||||
spacing: Tokens.spacing.medium
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
Layout.bottomMargin: -Tokens.spacing.medium
|
||||
spacing: Tokens.spacing.medium
|
||||
z: 1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import ZShell
|
||||
import ZShell.Blobs
|
||||
import ZShell.Config
|
||||
@@ -141,7 +142,8 @@ Item {
|
||||
}
|
||||
]
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: layout
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import Quickshell
|
||||
import ZShell.Config
|
||||
import ZShell.Internal
|
||||
|
||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Components
|
||||
import Quickshell
|
||||
import Quickshell.Widgets
|
||||
import ZShell.Config
|
||||
@@ -38,7 +39,7 @@ CustomListView {
|
||||
id: rowHover
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
id: rowLayout
|
||||
|
||||
anchors.left: parent.left
|
||||
|
||||
@@ -23,7 +23,7 @@ Item {
|
||||
service: Memory
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
id: layout
|
||||
anchors.fill: parent
|
||||
spacing: Tokens.spacing.medium
|
||||
@@ -60,13 +60,14 @@ Item {
|
||||
Layout.fillHeight: true
|
||||
implicitHeight: mainLayout.implicitHeight + mainLayout.anchors.margins * 2
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: mainLayout
|
||||
anchors.fill: parent
|
||||
anchors.margins: Tokens.padding.large
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
spacing: Tokens.spacing.small
|
||||
|
||||
MaterialIcon {
|
||||
@@ -131,7 +132,8 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: infoColumn
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
+57
-32
@@ -4,6 +4,8 @@ import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Templates
|
||||
import Quickshell
|
||||
import ZShell
|
||||
import ZShell.Components
|
||||
import ZShell.Config
|
||||
import qs.Components
|
||||
import qs.Services
|
||||
@@ -16,9 +18,17 @@ Item {
|
||||
required property var tabs
|
||||
|
||||
readonly property alias count: bar.count
|
||||
readonly property int tabIndicatorSpacing: Tokens.spacing.small
|
||||
readonly property int tabIndicatorSpacing: ZUtils.snap(Tokens.spacing.small, root)
|
||||
|
||||
implicitHeight: bar.implicitHeight + bar.anchors.topMargin + indicator.implicitHeight + indicator.anchors.topMargin + separator.implicitHeight
|
||||
function snapLayoutHeight(v) {
|
||||
const dpr = ZUtils.dprFor(root);
|
||||
let h = Math.ceil(v);
|
||||
while (Math.abs(h * dpr - Math.round(h * dpr)) > 1e-6)
|
||||
++h;
|
||||
return h;
|
||||
}
|
||||
|
||||
implicitHeight: ZUtils.snap(bar.implicitHeight + bar.anchors.topMargin + indicator.implicitHeight + indicator.anchors.topMargin + separator.implicitHeight, root)
|
||||
|
||||
TabBar {
|
||||
id: bar
|
||||
@@ -31,9 +41,11 @@ Item {
|
||||
currentIndex: root.screenState.dashboardTab
|
||||
onCurrentIndexChanged: root.screenState.dashboardTab = currentIndex
|
||||
|
||||
implicitHeight: contentHeight
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
implicitHeight: implicitContentHeight
|
||||
background: null
|
||||
contentItem: RowLayout {
|
||||
contentItem: SnapLayout {
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
@@ -116,10 +128,13 @@ Item {
|
||||
readonly property bool current: TabBar.tabBar.currentItem === this
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1 // Uniform width across all tabs
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: 1
|
||||
implicitWidth: implicitContentWidth
|
||||
implicitHeight: implicitContentHeight
|
||||
background: null
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
contentItem: CustomMouseArea {
|
||||
id: mouse
|
||||
@@ -131,8 +146,8 @@ Item {
|
||||
root.screenState.dashboardTab = Math.max(root.screenState.dashboardTab - 1, 0);
|
||||
}
|
||||
|
||||
implicitWidth: Math.max(icon.width, label.width)
|
||||
implicitHeight: icon.height + label.height
|
||||
implicitWidth: Math.max(icon.implicitWidth, label.implicitWidth)
|
||||
implicitHeight: snapLayout.implicitHeight
|
||||
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
@@ -146,39 +161,49 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
implicitHeight: parent.height + root.tabIndicatorSpacing * 2
|
||||
anchors.alignWhenCentered: false
|
||||
implicitHeight: ZUtils.snap(parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2, stateLayer)
|
||||
|
||||
radius: Tokens.rounding.medium
|
||||
color: tab.current ? Colors.palette.m3primary : Colors.palette.m3onSurface
|
||||
onClicked: root.screenState.dashboardTab = tab.TabBar.index
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
id: icon
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: label.top
|
||||
|
||||
text: tab.iconName
|
||||
color: tab.current ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
|
||||
fill: tab.current ? 1 : 0
|
||||
fontStyle: Tokens.font.icon.medium
|
||||
|
||||
Behavior on fill {
|
||||
Anim {
|
||||
type: Anim.DefaultEffects
|
||||
}
|
||||
onClicked: {
|
||||
root.screenState.dashboardTab = tab.TabBar.index;
|
||||
}
|
||||
}
|
||||
|
||||
CustomText {
|
||||
id: label
|
||||
SnapLayout {
|
||||
id: snapLayout
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
orientation: Qt.Vertical
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
MaterialIcon {
|
||||
id: icon
|
||||
|
||||
text: tab.text
|
||||
color: tab.current ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
|
||||
text: tab.iconName
|
||||
color: tab.current ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
|
||||
fill: tab.current ? 1 : 0
|
||||
fontStyle: Tokens.font.icon.medium
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Behavior on fill {
|
||||
Anim {
|
||||
type: Anim.DefaultEffects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomText {
|
||||
id: label
|
||||
|
||||
text: tab.text
|
||||
color: tab.current ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell
|
||||
import ZShell.Components
|
||||
import ZShell.Config
|
||||
import qs.Components
|
||||
import qs.Services
|
||||
import qs.Helpers
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
id: root
|
||||
|
||||
spacing: Tokens.spacing.largeIncreased
|
||||
@@ -20,7 +22,7 @@ RowLayout {
|
||||
|
||||
readonly property real markerX: {
|
||||
const d = root.now;
|
||||
return d.getHours() + d.getMinutes() / 60;
|
||||
return ZUtils.snap(d.getHours() + d.getMinutes() / 60, root);
|
||||
}
|
||||
|
||||
function formatHour(h) {
|
||||
@@ -39,11 +41,13 @@ RowLayout {
|
||||
onTriggered: root.now = new Date()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: root.width / 2
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
MaterialIcon {
|
||||
@@ -90,11 +94,13 @@ RowLayout {
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: root.width / 2
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
MaterialIcon {
|
||||
|
||||
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import ZShell.Config
|
||||
import ZShell.Components
|
||||
import qs.Components
|
||||
import qs.Modules.Dashboard.Weather
|
||||
import qs.Services
|
||||
@@ -18,13 +19,14 @@ Item {
|
||||
implicitHeight: layout.implicitHeight
|
||||
Component.onCompleted: Weather.reload()
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: layout
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: Tokens.spacing.medium
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
Layout.leftMargin: Tokens.padding.large
|
||||
Layout.rightMargin: Tokens.padding.large
|
||||
Layout.fillWidth: true
|
||||
@@ -82,7 +84,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Tokens.spacing.medium
|
||||
|
||||
@@ -121,7 +123,9 @@ Item {
|
||||
color: Colors.palette.m3onSurface
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
SnapLayout {
|
||||
id: forecastLayout
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: Tokens.spacing.medium
|
||||
|
||||
@@ -137,12 +141,14 @@ Item {
|
||||
required property var modelData
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
implicitHeight: forecastItemColumn.implicitHeight + Tokens.padding.medium * 2
|
||||
|
||||
radius: root.radius
|
||||
color: Colors.tPalette.m3surfaceContainer
|
||||
|
||||
ColumnLayout {
|
||||
SnapLayout {
|
||||
orientation: Qt.Vertical
|
||||
id: forecastItemColumn
|
||||
|
||||
anchors.centerIn: parent
|
||||
@@ -196,7 +202,8 @@ Item {
|
||||
property color colour
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 60
|
||||
Layout.fillHeight: true
|
||||
implicitHeight: 60
|
||||
radius: Tokens.rounding.medium
|
||||
color: Colors.tPalette.m3surfaceContainer
|
||||
|
||||
@@ -230,7 +237,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
component WeatherStat: RowLayout {
|
||||
component WeatherStat: SnapLayout {
|
||||
id: weatherStat
|
||||
|
||||
property string icon
|
||||
|
||||
Reference in New Issue
Block a user