first commit
This commit is contained in:
331
bar/modules/Clock.qml
Normal file
331
bar/modules/Clock.qml
Normal file
@@ -0,0 +1,331 @@
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Wayland
|
||||
|
||||
import "../../config" as Cfg
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property real panelRadius: Cfg.Config.radius / 2
|
||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
||||
|
||||
property bool isTop: true
|
||||
property var targetScreen: null
|
||||
property int barHeight: Cfg.Config.barHeight
|
||||
property int barMargin: Cfg.Config.margin
|
||||
|
||||
readonly property var t: Cfg.Config.theme
|
||||
|
||||
readonly property int tzOffsetHours: -timeManager.now.getTimezoneOffset() / 60
|
||||
|
||||
width: clockLayout.implicitWidth + 24
|
||||
height: Cfg.Config.moduleHeight
|
||||
radius: panelRadius
|
||||
|
||||
color: hoverHandler.hovered ? t.clockBgHover : t.clockBg
|
||||
border.color: hoverHandler.hovered ? t.clockBorderHover : t.clockBorder
|
||||
border.width: borderWidth
|
||||
|
||||
anchors.right: parent.right
|
||||
|
||||
Behavior on width { NumberAnimation { duration: 250; easing.type: Easing.OutCubic } }
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||
|
||||
HoverHandler {
|
||||
id: hoverHandler
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onTapped: calendarPopup.toggle()
|
||||
}
|
||||
|
||||
Item {
|
||||
id: timeManager
|
||||
property date now: new Date()
|
||||
Timer {
|
||||
interval: 1000; running: true; repeat: true
|
||||
onTriggered: timeManager.now = new Date()
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: clockLayout
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
Text {
|
||||
text: ""
|
||||
color: root.t.clockIcon
|
||||
font.pixelSize: 14
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.rightMargin: 8
|
||||
}
|
||||
|
||||
Text {
|
||||
text: timeManager.now.toLocaleTimeString(Qt.locale(), "HH:mm")
|
||||
color: root.t.clockTime
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
id: secondsText
|
||||
text: ":" + timeManager.now.toLocaleTimeString(Qt.locale(), "ss")
|
||||
color: root.t.clockSeconds
|
||||
font.pixelSize: 13
|
||||
font.bold: true
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
opacity: (hoverHandler.hovered || calendarPopup.popupOpen) ? 1.0 : 0.0
|
||||
visible: opacity > 0
|
||||
Layout.preferredWidth: (hoverHandler.hovered || calendarPopup.popupOpen) ? implicitWidth : 0
|
||||
clip: true
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
Behavior on Layout.preferredWidth { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
|
||||
}
|
||||
}
|
||||
|
||||
PanelWindow {
|
||||
id: calendarPopup
|
||||
screen: root.targetScreen
|
||||
visible: false
|
||||
color: "transparent"
|
||||
|
||||
property bool popupOpen: false
|
||||
|
||||
function open() { hideTimer.stop(); visible = true; popupOpen = true }
|
||||
function close() { popupOpen = false; hideTimer.restart() }
|
||||
function toggle() { popupOpen ? close() : open() }
|
||||
|
||||
Timer {
|
||||
id: hideTimer
|
||||
interval: Cfg.Config.popupAnimDuration + 70
|
||||
onTriggered: calendarPopup.visible = false
|
||||
}
|
||||
|
||||
anchors { top: true; bottom: true; left: true; right: true }
|
||||
WlrLayershell.layer: WlrLayer.Top
|
||||
WlrLayershell.namespace: "main-shell-calendar"
|
||||
WlrLayershell.exclusiveZone: -1
|
||||
mask: popupOpen ? null : _noInput
|
||||
Region { id: _noInput }
|
||||
|
||||
TapHandler { onTapped: calendarPopup.close() }
|
||||
|
||||
Item {
|
||||
id: calClipContainer
|
||||
readonly property int cardW: 284
|
||||
readonly property int screenPad: root.barMargin + 10
|
||||
|
||||
x: {
|
||||
let centerX = root.mapToItem(null, 0, 0).x + root.width / 2
|
||||
let desiredX = centerX - cardW / 2
|
||||
return Math.max(screenPad, Math.min(desiredX, parent.width - cardW - screenPad))
|
||||
}
|
||||
width: cardW
|
||||
|
||||
anchors.top: root.isTop ? parent.top : undefined
|
||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
||||
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0
|
||||
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10)
|
||||
height: parent.height - root.barHeight - 10
|
||||
|
||||
clip: true
|
||||
|
||||
Rectangle {
|
||||
id: card
|
||||
width: parent.width
|
||||
height: cardCol.implicitHeight + 24
|
||||
|
||||
anchors.top: root.isTop ? parent.top : undefined
|
||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
||||
|
||||
transform: Translate {
|
||||
y: calendarPopup.popupOpen ? 0 : (root.isTop ? -card.height : card.height)
|
||||
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: Cfg.Config.popupAnimDuration;
|
||||
easing.type: Easing.OutExpo
|
||||
}
|
||||
enabled: calendarPopup.visible
|
||||
}
|
||||
}
|
||||
|
||||
opacity: calendarPopup.popupOpen ? 1.0 : 0.0
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
|
||||
color: root.t.calCardBg
|
||||
radius: Cfg.Config.popupRadius
|
||||
border.color: root.t.calCardBorder
|
||||
border.width: Cfg.Config.popupBorderWidth
|
||||
layer.enabled: true
|
||||
|
||||
MouseArea { anchors.fill: parent; propagateComposedEvents: false }
|
||||
|
||||
ColumnLayout {
|
||||
id: cardCol
|
||||
anchors { left: parent.left; right: parent.right; top: parent.top }
|
||||
anchors.margins: 16
|
||||
anchors.topMargin: 18
|
||||
spacing: 14
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 2
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text {
|
||||
text: timeManager.now.toLocaleDateString(Qt.locale(), "dddd")
|
||||
color: root.t.clockPopupDim
|
||||
font.pixelSize: 12
|
||||
font.capitalization: Font.AllUppercase
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
Text {
|
||||
text: timeManager.now.toLocaleDateString(Qt.locale(), "d MMMM yyyy")
|
||||
color: root.t.clockPopupHeader
|
||||
font.pixelSize: 22
|
||||
font.bold: true
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: root.t.calSeparator }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text {
|
||||
text: "‹"; color: root.t.clockPopupDim; font.pixelSize: 18; font.bold: true
|
||||
MouseArea {
|
||||
anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
cal.displayMonth -= 1
|
||||
if (cal.displayMonth < 0) { cal.displayMonth = 11; cal.displayYear -= 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: new Date(cal.displayYear, cal.displayMonth, 1).toLocaleDateString(Qt.locale(), "MMMM yyyy")
|
||||
color: root.t.clockPopupText
|
||||
font.pixelSize: 13; font.bold: true
|
||||
Layout.fillWidth: true; horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "›"; color: root.t.clockPopupDim; font.pixelSize: 18; font.bold: true
|
||||
MouseArea {
|
||||
anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
cal.displayMonth += 1
|
||||
if (cal.displayMonth > 11) { cal.displayMonth = 0; cal.displayYear += 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: cal
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: gridCol.implicitHeight
|
||||
property int displayYear: timeManager.now.getFullYear()
|
||||
property int displayMonth: timeManager.now.getMonth()
|
||||
|
||||
Connections {
|
||||
target: calendarPopup
|
||||
function onPopupOpenChanged() {
|
||||
if (calendarPopup.popupOpen) {
|
||||
cal.displayYear = timeManager.now.getFullYear()
|
||||
cal.displayMonth = timeManager.now.getMonth()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: gridCol
|
||||
anchors.fill: parent
|
||||
spacing: 2
|
||||
|
||||
Row {
|
||||
spacing: 0
|
||||
Repeater {
|
||||
model: ["Mo","Tu","We","Th","Fr","Sa","Su"]
|
||||
Text {
|
||||
width: (card.width - 32) / 7
|
||||
text: modelData; color: root.t.clockPopupDim
|
||||
font.pixelSize: 11; horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: 6
|
||||
Row {
|
||||
id: weekRow
|
||||
property int weekIndex: index
|
||||
Repeater {
|
||||
model: 7
|
||||
delegate: Item {
|
||||
width: (card.width - 32) / 7; height: 26
|
||||
readonly property int dayNum: (weekRow.weekIndex * 7 + index) - ((new Date(cal.displayYear, cal.displayMonth, 1).getDay() + 6) % 7) + 1
|
||||
readonly property bool inMonth: dayNum >= 1 && dayNum <= new Date(cal.displayYear, cal.displayMonth + 1, 0).getDate()
|
||||
readonly property bool isToday: inMonth && dayNum === timeManager.now.getDate() && cal.displayYear === timeManager.now.getFullYear() && cal.displayMonth === timeManager.now.getMonth()
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent; width: 22; height: 22; radius: 11
|
||||
color: isToday ? root.t.accent : "transparent"
|
||||
visible: inMonth
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: inMonth ? dayNum : ""
|
||||
color: isToday ? root.t.todayText : (index >= 5 ? root.t.clockPopupDim : root.t.clockPopupText)
|
||||
font.pixelSize: 12; font.bold: isToday
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: root.t.calSeparator }
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true; spacing: 12
|
||||
Text { text: ""; color: root.t.clockIcon; font.pixelSize: 16 }
|
||||
ColumnLayout {
|
||||
spacing: 0; Layout.fillWidth: true
|
||||
Text {
|
||||
text: timeManager.now.toLocaleTimeString(Qt.locale(), "t") || "UTC"
|
||||
color: root.t.clockPopupText; font.pixelSize: 12; font.bold: true
|
||||
}
|
||||
Text {
|
||||
text: "UTC " + (root.tzOffsetHours >= 0 ? "+" : "") + root.tzOffsetHours
|
||||
color: root.t.clockPopupDim; font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: timeManager.now.toLocaleTimeString(Qt.locale(), "HH:mm:ss")
|
||||
color: root.t.clockTime; font.pixelSize: 20; font.bold: true; font.family: "monospace"
|
||||
}
|
||||
}
|
||||
|
||||
Item { height: 4 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user