diff options
Diffstat (limited to 'accounts/gkleen@sif/shell/quickshell/Clock.qml')
-rw-r--r-- | accounts/gkleen@sif/shell/quickshell/Clock.qml | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/accounts/gkleen@sif/shell/quickshell/Clock.qml b/accounts/gkleen@sif/shell/quickshell/Clock.qml new file mode 100644 index 00000000..edce57e3 --- /dev/null +++ b/accounts/gkleen@sif/shell/quickshell/Clock.qml | |||
@@ -0,0 +1,264 @@ | |||
1 | import QtQml | ||
2 | import QtQuick | ||
3 | import Quickshell | ||
4 | import Custom as Custom | ||
5 | import QtQuick.Controls | ||
6 | import QtQuick.Layouts | ||
7 | import Quickshell.Widgets | ||
8 | |||
9 | Item { | ||
10 | id: clockItem | ||
11 | |||
12 | width: clock.contentWidth | ||
13 | height: parent.height | ||
14 | anchors.verticalCenter: parent.verticalCenter | ||
15 | |||
16 | WrapperMouseArea { | ||
17 | id: clockMouseArea | ||
18 | |||
19 | anchors.fill: parent | ||
20 | hoverEnabled: true | ||
21 | enabled: true | ||
22 | |||
23 | property real angleRem: 0 | ||
24 | property real sensitivity: 1 / 120 | ||
25 | |||
26 | function scrollYear(event) { | ||
27 | angleRem += event.angleDelta.y; | ||
28 | const d = Math.round(angleRem * sensitivity); | ||
29 | yearCalendar.year += d; | ||
30 | angleRem -= d / sensitivity; | ||
31 | } | ||
32 | |||
33 | onWheel: event => scrollYear(event) | ||
34 | |||
35 | Item { | ||
36 | anchors.fill: parent | ||
37 | |||
38 | Text { | ||
39 | id: clock | ||
40 | color: "white" | ||
41 | |||
42 | anchors.verticalCenter: parent.verticalCenter | ||
43 | |||
44 | Custom.Chrono { | ||
45 | id: chrono | ||
46 | |||
47 | onDateChanged: clock.text = format("W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}") | ||
48 | } | ||
49 | |||
50 | font.pointSize: 10 | ||
51 | font.family: "Fira Sans" | ||
52 | font.features: { "tnum": 1 } | ||
53 | } | ||
54 | } | ||
55 | } | ||
56 | |||
57 | PopupWindow { | ||
58 | id: tooltip | ||
59 | |||
60 | property bool nextVisible: clockMouseArea.containsMouse || tooltipMouseArea.containsMouse | ||
61 | |||
62 | anchor { | ||
63 | item: clockMouseArea | ||
64 | edges: Edges.Bottom | Edges.Left | ||
65 | } | ||
66 | visible: false | ||
67 | |||
68 | onNextVisibleChanged: hangTimer.restart() | ||
69 | |||
70 | Timer { | ||
71 | id: hangTimer | ||
72 | interval: 100 | ||
73 | onTriggered: tooltip.visible = tooltip.nextVisible | ||
74 | } | ||
75 | |||
76 | implicitWidth: clockTooltipContent.width | ||
77 | implicitHeight: clockTooltipContent.height | ||
78 | color: "black" | ||
79 | |||
80 | onVisibleChanged: { | ||
81 | yearCalendar.year = chrono.date.getFullYear(); | ||
82 | clockMouseArea.angleRem = 0; | ||
83 | } | ||
84 | |||
85 | WrapperMouseArea { | ||
86 | id: tooltipMouseArea | ||
87 | |||
88 | hoverEnabled: true | ||
89 | enabled: true | ||
90 | |||
91 | onWheel: event => clockMouseArea.scrollYear(event) | ||
92 | |||
93 | anchors.fill: parent | ||
94 | |||
95 | WrapperItem { | ||
96 | id: clockTooltipContent | ||
97 | |||
98 | margin: 8 | ||
99 | leftMargin: 0 | ||
100 | |||
101 | ColumnLayout { | ||
102 | Text { | ||
103 | id: yearLabel | ||
104 | |||
105 | horizontalAlignment: Text.AlignHCenter | ||
106 | |||
107 | font.pointSize: 14 | ||
108 | font.family: "Fira Sans" | ||
109 | font.features: { "tnum": 1 } | ||
110 | color: "white" | ||
111 | |||
112 | text: yearCalendar.year | ||
113 | |||
114 | Layout.fillWidth: true | ||
115 | Layout.bottomMargin: 8 | ||
116 | } | ||
117 | |||
118 | GridLayout { | ||
119 | property int year: chrono.date.getFullYear() | ||
120 | |||
121 | id: yearCalendar | ||
122 | |||
123 | columns: 3 | ||
124 | columnSpacing: 16 | ||
125 | rowSpacing: 16 | ||
126 | |||
127 | Layout.alignment: Qt.AlignHCenter | ||
128 | Layout.fillWidth: false | ||
129 | |||
130 | Repeater { | ||
131 | model: 12 | ||
132 | |||
133 | GridLayout { | ||
134 | columns: 2 | ||
135 | |||
136 | required property int index | ||
137 | property int month: index | ||
138 | |||
139 | id: monthCalendar | ||
140 | |||
141 | Layout.alignment: Qt.AlignTop | Qt.AlignRight | ||
142 | Layout.fillWidth: false | ||
143 | |||
144 | Text { | ||
145 | Layout.column: 1 | ||
146 | Layout.fillWidth: true | ||
147 | |||
148 | horizontalAlignment: Text.AlignHCenter | ||
149 | |||
150 | font.pointSize: 10 | ||
151 | font.family: "Fira Sans" | ||
152 | |||
153 | text: new Date(yearCalendar.year, monthCalendar.month, 1).toLocaleString(Qt.locale("en_DK"), "MMMM") | ||
154 | |||
155 | color: "#ffead3" | ||
156 | } | ||
157 | |||
158 | DayOfWeekRow { | ||
159 | locale: grid.locale | ||
160 | |||
161 | Layout.row: 1 | ||
162 | Layout.column: 1 | ||
163 | Layout.fillWidth: true | ||
164 | |||
165 | delegate: WrapperItem { | ||
166 | required property string shortName | ||
167 | |||
168 | width: dowLabel.contentWidth + 6 | ||
169 | |||
170 | Text { | ||
171 | id: dowLabel | ||
172 | |||
173 | anchors.fill: parent | ||
174 | |||
175 | font.pointSize: 10 | ||
176 | font.family: "Fira Sans" | ||
177 | |||
178 | text: parent.shortName | ||
179 | color: "#ffcc66" | ||
180 | |||
181 | horizontalAlignment: Text.AlignHCenter | ||
182 | verticalAlignment: Text.AlignVCenter | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | WeekNumberColumn { | ||
188 | month: grid.month | ||
189 | year: grid.year | ||
190 | locale: grid.locale | ||
191 | |||
192 | Layout.fillHeight: true | ||
193 | |||
194 | delegate: Text { | ||
195 | required property int weekNumber | ||
196 | |||
197 | opacity: { | ||
198 | const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7); | ||
199 | const dayOfWeek = simple.getDay(); | ||
200 | const isoWeekStart = simple; | ||
201 | |||
202 | isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1); | ||
203 | if (dayOfWeek > 4) { | ||
204 | isoWeekStart.setDate(isoWeekStart.getDate() + 7); | ||
205 | } | ||
206 | |||
207 | for (let i = 0; i < 7; i++) { | ||
208 | const dayInWeek = new Date(isoWeekStart); | ||
209 | dayInWeek.setDate(dayInWeek.getDate() + i); | ||
210 | if (dayInWeek.getMonth() == monthCalendar.month) | ||
211 | return 1; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | font.pointSize: 10 | ||
218 | font.family: "Fira Sans" | ||
219 | font.features: { "tnum": 1 } | ||
220 | |||
221 | text: weekNumber | ||
222 | color: "#99ffdd" | ||
223 | |||
224 | horizontalAlignment: Text.AlignRight | ||
225 | verticalAlignment: Text.AlignVCenter | ||
226 | } | ||
227 | } | ||
228 | |||
229 | MonthGrid { | ||
230 | id: grid | ||
231 | |||
232 | year: yearCalendar.year | ||
233 | month: monthCalendar.month | ||
234 | locale: Qt.locale("en_DK") | ||
235 | |||
236 | Layout.fillWidth: true | ||
237 | Layout.fillHeight: true | ||
238 | |||
239 | delegate: Text { | ||
240 | required property var model | ||
241 | |||
242 | opacity: model.month === monthCalendar.month ? 1 : 0 | ||
243 | |||
244 | font.pointSize: 10 | ||
245 | font.family: "Fira Sans" | ||
246 | font.features: { "tnum": 1 } | ||
247 | |||
248 | property bool today: chrono.date.getFullYear() == model.year && chrono.date.getMonth() == model.month && chrono.date.getDate() == model.day | ||
249 | |||
250 | text: model.day | ||
251 | color: today ? "#ff6699" : "white" | ||
252 | |||
253 | horizontalAlignment: Text.AlignRight | ||
254 | verticalAlignment: Text.AlignVCenter | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | } | ||
264 | } | ||