added quickshell
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import "root:/config"
|
||||
import "root:/components"
|
||||
import "root:/services"
|
||||
|
||||
// Month grid with the current day slashed in crimson, plus uptime and a couple
|
||||
// of world clocks.
|
||||
Popout {
|
||||
id: root
|
||||
|
||||
property date clockDate: new Date()
|
||||
|
||||
contentWidth: 320
|
||||
contentHeight: 352
|
||||
|
||||
// Month currently on display, as an offset from the real one.
|
||||
property int monthOffset: 0
|
||||
|
||||
onShownChanged: if (!shown) monthOffset = 0
|
||||
|
||||
readonly property date viewDate: {
|
||||
const d = new Date(root.clockDate);
|
||||
d.setDate(1);
|
||||
d.setMonth(d.getMonth() + root.monthOffset);
|
||||
return d;
|
||||
}
|
||||
|
||||
readonly property int viewYear: viewDate.getFullYear()
|
||||
readonly property int viewMonth: viewDate.getMonth()
|
||||
|
||||
// Monday-first grid, 6 rows of 7.
|
||||
readonly property var cells: {
|
||||
const first = new Date(root.viewYear, root.viewMonth, 1);
|
||||
const lead = (first.getDay() + 6) % 7;
|
||||
const start = new Date(root.viewYear, root.viewMonth, 1 - lead);
|
||||
const out = [];
|
||||
for (let i = 0; i < 42; i++) {
|
||||
const d = new Date(start);
|
||||
d.setDate(start.getDate() + i);
|
||||
out.push({
|
||||
day: d.getDate(),
|
||||
inMonth: d.getMonth() === root.viewMonth,
|
||||
today: d.toDateString() === root.clockDate.toDateString()
|
||||
});
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
PopoutSurface {
|
||||
anchors.fill: parent
|
||||
tone: Theme.accent
|
||||
|
||||
PopoutHeader {
|
||||
id: header
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
title: Qt.formatDateTime(root.viewDate, "MMMM")
|
||||
icon: ""
|
||||
accent: Theme.accent
|
||||
subtitle: Qt.formatDateTime(root.viewDate, "yyyy")
|
||||
}
|
||||
|
||||
// Month stepper.
|
||||
Row {
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: Theme.padS
|
||||
anchors.right: parent.right
|
||||
spacing: Theme.padS
|
||||
z: 2
|
||||
|
||||
StepButton {
|
||||
glyph: ""
|
||||
onClicked: root.monthOffset--
|
||||
}
|
||||
|
||||
StepButton {
|
||||
glyph: ""
|
||||
onClicked: root.monthOffset++
|
||||
}
|
||||
}
|
||||
|
||||
// Weekday header, clear of the month stepper above it.
|
||||
Row {
|
||||
id: dayNames
|
||||
anchors.top: header.bottom
|
||||
anchors.topMargin: 36
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Repeater {
|
||||
model: ["MO", "TU", "WE", "TH", "FR", "SA", "SU"]
|
||||
|
||||
Text {
|
||||
required property var modelData
|
||||
required property int index
|
||||
|
||||
width: dayNames.width / 7
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: modelData
|
||||
color: index >= 5 ? Theme.alpha(Theme.accent, 0.8) : Theme.muted
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 8
|
||||
font.letterSpacing: 1
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: grid
|
||||
anchors.top: dayNames.bottom
|
||||
anchors.topMargin: Theme.padS
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
columns: 7
|
||||
|
||||
Repeater {
|
||||
model: root.cells
|
||||
|
||||
Item {
|
||||
id: cell
|
||||
required property var modelData
|
||||
|
||||
width: grid.width / 7
|
||||
height: 30
|
||||
|
||||
// Today gets a leaning crimson slab.
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: 26
|
||||
height: 24
|
||||
visible: cell.modelData.today
|
||||
color: Theme.accent
|
||||
|
||||
transform: Matrix4x4 {
|
||||
matrix: Qt.matrix4x4(1, -Theme.skew, 0, 24 * Theme.skew,
|
||||
0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: cell.modelData.day
|
||||
color: {
|
||||
if (cell.modelData.today) return Theme.text;
|
||||
if (!cell.modelData.inMonth) return Theme.alpha(Theme.muted, 0.45);
|
||||
return Theme.subtext;
|
||||
}
|
||||
font.family: Theme.fontDisplay
|
||||
font.pixelSize: Theme.fsSmall
|
||||
font.italic: true
|
||||
font.weight: cell.modelData.today ? Font.Black : Font.Medium
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Footer: uptime and a second time zone.
|
||||
Row {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Column {
|
||||
width: parent.width / 2
|
||||
spacing: -2
|
||||
|
||||
Text {
|
||||
text: "UPTIME"
|
||||
color: Theme.muted
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 8
|
||||
font.letterSpacing: 1.5
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Text {
|
||||
text: Sys.uptime
|
||||
color: Theme.text
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: Theme.fsSmall
|
||||
font.weight: Font.DemiBold
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width / 2
|
||||
spacing: -2
|
||||
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
text: "TOKYO"
|
||||
color: Theme.muted
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 8
|
||||
font.letterSpacing: 1.5
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
text: {
|
||||
// Tokyo is UTC+9 year-round.
|
||||
const utc = root.clockDate.getTime()
|
||||
+ root.clockDate.getTimezoneOffset() * 60000;
|
||||
const tokyo = new Date(utc + 9 * 3600000);
|
||||
return Qt.formatDateTime(tokyo, "HH:mm");
|
||||
}
|
||||
color: Theme.primary
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: Theme.fsSmall
|
||||
font.weight: Font.DemiBold
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component StepButton: Item {
|
||||
id: step
|
||||
|
||||
property string glyph: ""
|
||||
signal clicked()
|
||||
|
||||
implicitWidth: 22
|
||||
implicitHeight: 22
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: stepHover.hovered ? Theme.alpha(Theme.accent, 0.25) : "transparent"
|
||||
border.width: 1
|
||||
border.color: Theme.alpha(Theme.outline, 0.7)
|
||||
|
||||
transform: Matrix4x4 {
|
||||
matrix: Qt.matrix4x4(1, -Theme.skew, 0, 22 * Theme.skew,
|
||||
0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
|
||||
}
|
||||
}
|
||||
|
||||
Icon {
|
||||
anchors.centerIn: parent
|
||||
text: step.glyph
|
||||
color: stepHover.hovered ? Theme.text : Theme.subtext
|
||||
font.pixelSize: Theme.fsBody
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: stepHover
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onTapped: step.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user