Skip to content

Commit 0f6bca2

Browse files
committed
feat: Implement day-night modes and move logic into DayNightController.qml
1 parent 9451925 commit 0f6bca2

6 files changed

Lines changed: 197 additions & 70 deletions

File tree

package/contents/config/main.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,22 @@
137137
<entry name="ChangeWallpaperTimerHours" type="Int">
138138
<default>0</default>
139139
</entry>
140-
<entry name="DayNightCycle" type="Bool">
140+
<entry name="DayNightCycleEnabled" type="Bool">
141141
<label>Whether or not to cycle between day and night wallpapers</label>
142142
<default>False</default>
143143
</entry>
144+
<entry name="DayNightCycleMode" type="Int">
145+
<label>Mode</label>
146+
<default>0</default>
147+
</entry>
148+
<entry name="DayNightCycleSunriseTime" type="Int">
149+
<label>Time of sunrise</label>
150+
<default>360</default>
151+
</entry>
152+
<entry name="DayNightCycleSunsetTime" type="Int">
153+
<label>Time of sunset</label>
154+
<default>1080</default>
155+
</entry>
144156
<entry name="ResumeLastVideo" type="Bool">
145157
<label>Whether or not to resume last playing video on startup</label>
146158
<default>True</default>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import QtQuick
2+
import "code/enum.js" as Enum
3+
4+
Item {
5+
id: root
6+
required property bool enabled
7+
required property int mode
8+
required property int sunriseTime
9+
required property int sunsetTime
10+
11+
required property bool isLoading
12+
13+
function detectDayTime(mode: int, sunriseTime: int, sunsetTime: int): bool {
14+
switch (root.mode) {
15+
case Enum.DayNightCycleMode.Time:
16+
const now = new Date();
17+
const currentTime = now.getHours() * 60 + now.getMinutes();
18+
19+
return currentTime >= root.sunriseTime && currentTime < root.sunsetTime;
20+
case Enum.DayNightCycleMode.PlasmaStyle: return Qt.styleHints.colorScheme === Qt.ColorScheme.Light;
21+
case Enum.DayNightCycleMode.AlwaysNight: return false;
22+
case Enum.DayNightCycleMode.AlwaysDay: return true;
23+
}
24+
}
25+
26+
property bool isDay: true
27+
28+
signal beforeChanged;
29+
signal changed;
30+
31+
Timer {
32+
id: timer
33+
interval: 1000
34+
running: true
35+
repeat: true
36+
triggeredOnStart: true
37+
property bool prevEnabled: root.enabled
38+
onTriggered: {
39+
const enableChanged = timer.prevEnabled !== root.enabled;
40+
if ((!enableChanged && !root.enabled) || root.isLoading) {
41+
return;
42+
}
43+
timer.prevEnabled = root.enabled;
44+
45+
const isDay = root.detectDayTime(root.mode, root.sunriseTime, root.sunsetTime);
46+
47+
if ((root.isDay != isDay) || enableChanged) {
48+
root.beforeChanged();
49+
root.isDay = isDay;
50+
root.changed();
51+
}
52+
}
53+
}
54+
55+
Component.onCompleted: {
56+
root.isDay = root.detectDayTime(root.mode, root.sunriseTime, root.sunsetTime);
57+
timer.start();
58+
}
59+
}

package/contents/ui/code/enum.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ const DayNightCycleAssignment = {
2222
Night: 2,
2323
};
2424

25+
const DayNightCycleMode = {
26+
Disabled: 0,
27+
Time: 1,
28+
PlasmaStyle: 2,
29+
AlwaysDay: 3,
30+
AlwaysNight: 4,
31+
};
32+
2533
const PauseMode = {
2634
MaximizedOrFullScreen: 0,
2735
ActiveWindowPresent: 1,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import QtQuick.Controls
2+
import QtQuick.Layouts
3+
4+
RowLayout {
5+
id: root
6+
required property string label
7+
property int value
8+
9+
Label {
10+
text: root.label
11+
}
12+
SpinBox {
13+
id: hours
14+
from: 0
15+
to: 23
16+
value: Math.floor(root.value / 60)
17+
editable: true
18+
textFromValue: (value) => value.toString().padStart(2, '0')
19+
valueFromText: (text) => parseInt(text, 10)
20+
onValueModified: {
21+
root.value = hours.value * 60 + minutes.value
22+
}
23+
}
24+
SpinBox {
25+
id: minutes
26+
from: 0
27+
to: 59
28+
value: root.value % 60
29+
editable: true
30+
textFromValue: (value) => value.toString().padStart(2, '0')
31+
valueFromText: (text) => parseInt(text, 10)
32+
onValueModified: {
33+
root.value = hours.value * 60 + minutes.value
34+
}
35+
}
36+
}

package/contents/ui/config.qml

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ ColumnLayout {
6464
property real cfg_PlaybackRate
6565
property real cfg_AlternativePlaybackRate
6666
property alias cfg_Volume: volumeSlider.value
67-
property alias cfg_DayNightCycle: dayNightCycleCheckBox.checked
67+
property bool cfg_DayNightCycleEnabled: dayNightCycleMode.currentValue !== Enum.DayNightCycleMode.Disabled
68+
property alias cfg_DayNightCycleMode: dayNightCycleMode.currentValue
69+
property alias cfg_DayNightCycleSunriseTime: dayNightCycleSunriseTime.value
70+
property alias cfg_DayNightCycleSunsetTime: dayNightCycleSunsetTime.value
6871
property alias cfg_RandomMode: randomModeCheckbox.checked
6972
property alias cfg_ResumeLastVideo: resumeLastVideoCheckbox.checked
7073
property alias cfg_ChangeWallpaperMode: changeWallpaperModeComboBox.currentValue
@@ -326,6 +329,52 @@ ColumnLayout {
326329
valueRole: "value"
327330
}
328331
}
332+
333+
RowLayout {
334+
Kirigami.FormData.label: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Day-Night Cycle:")
335+
visible: root.currentTab === 0
336+
337+
ComboBox {
338+
id: dayNightCycleMode
339+
model: [
340+
{
341+
text: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Disabled"),
342+
value: Enum.DayNightCycleMode.Disabled
343+
},
344+
{
345+
text: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Based on time"),
346+
value: Enum.DayNightCycleMode.Time
347+
},
348+
{
349+
text: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Based on Plasma Style"),
350+
value: Enum.DayNightCycleMode.PlasmaStyle
351+
},
352+
{
353+
text: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Always Day"),
354+
value: Enum.DayNightCycleMode.AlwaysDay
355+
},
356+
{
357+
text: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Always Night"),
358+
value: Enum.DayNightCycleMode.AlwaysNight
359+
}
360+
]
361+
textRole: "text"
362+
valueRole: "value"
363+
}
364+
}
365+
ColumnLayout {
366+
visible: root.currentTab === 0
367+
enabled: dayNightCycleMode.currentValue === Enum.DayNightCycleMode.Time
368+
Components.TimePicker {
369+
id: dayNightCycleSunriseTime
370+
label: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Sunrise:")
371+
}
372+
Components.TimePicker {
373+
id: dayNightCycleSunsetTime
374+
label: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Sunset: ")
375+
}
376+
}
377+
329378
// RowLayout {
330379
ButtonGroup {
331380
id: backgroundGroup
@@ -483,12 +532,6 @@ ColumnLayout {
483532
}
484533
}
485534

486-
CheckBox {
487-
id: dayNightCycleCheckBox
488-
Kirigami.FormData.label: i18n("Day/Night Cycle:")
489-
visible: root.currentTab === 1
490-
}
491-
492535
CheckBox {
493536
id: randomModeCheckbox
494537
Kirigami.FormData.label: i18nd("plasma_wallpaper_luisbocanegra.smart.video.wallpaper.reborn", "Random order:")

package/contents/ui/main.qml

Lines changed: 31 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,7 @@ WallpaperItem {
4242
}
4343
property int currentVideoIndex: 0
4444
property bool resumeLastVideo: main.configuration.ResumeLastVideo
45-
property bool dayNightCycle: main.configuration.DayNightCycle
46-
property bool isDay: {
47-
const currentTime = new Date().getHours();
48-
return currentTime >= 6 && currentTime < 19;
49-
}
50-
51-
function getLastVideo() {
52-
if (dayNightCycle) {
53-
return main.configuration[isDay ? "LastVideoDay" : "LastVideoNight"];
54-
}
55-
return main.configuration.LastVideo;
56-
}
57-
function getLastVideoIndex() {
58-
const lastVideo = getLastVideo();
59-
for (let index = 0; index < videosConfig.length; index++) {
60-
if (videosConfig[index].filename === lastVideo) {
61-
return index;
62-
}
63-
}
64-
65-
return 0;
66-
}
67-
45+
property alias isDay: dayNightCycleController.isDay
6846
property var currentSource: {
6947
const lastVideo = getLastVideo();
7048
if (resumeLastVideo && lastVideo !== "") {
@@ -220,7 +198,7 @@ WallpaperItem {
220198
}
221199

222200
function getVideos() {
223-
if (dayNightCycle) {
201+
if (main.configuration.DayNightCycleEnabled) {
224202
return Utils.parseCompat(videoUrls).filter(video => {
225203
const isDayCycle = video.dayNightCycleAssignment !== Enum.DayNightCycleAssignment.Night;
226204
const isNightCycle = video.dayNightCycleAssignment !== Enum.DayNightCycleAssignment.Day;
@@ -231,6 +209,21 @@ WallpaperItem {
231209

232210
return Utils.parseCompat(videoUrls).filter(video => video.enabled);
233211
}
212+
function getLastVideo() {
213+
if (main.configuration.DayNightCycleEnabled) {
214+
return main.configuration[main.isDay ? "LastVideoDay" : "LastVideoNight"];
215+
}
216+
return main.configuration.LastVideo;
217+
}
218+
function getLastVideoIndex() {
219+
const lastVideo = getLastVideo();
220+
for (let index = 0; index < videosConfig.length; index++) {
221+
if (videosConfig[index].filename === lastVideo) {
222+
return index;
223+
}
224+
}
225+
return 0;
226+
}
234227

235228
onPlayingChanged: {
236229
playing && !isLoading ? main.play() : main.pause();
@@ -293,42 +286,19 @@ WallpaperItem {
293286
}
294287
}
295288

296-
Timer {
297-
id: dayNightCycleTimer
298-
interval: 1000
299-
running: true
300-
repeat: true
301-
triggeredOnStart: true
302-
onTriggered: {
303-
const dayNightCycleConfigChanged = dayNightCycle !== main.configuration.DayNightCycle;
304-
if (!dayNightCycleConfigChanged && !main.configuration.DayNightCycle) {
305-
return;
306-
}
307-
dayNightCycle = main.configuration.DayNightCycle;
308-
309-
const hours = new Date().getHours();
310-
const isDay = hours >= 6 && hours < 19;
311-
312-
if ((main.isDay != isDay) || dayNightCycleConfigChanged) {
313-
main.save();
314-
main.isDay = isDay;
315-
videosConfig = getVideos();
316-
317-
if (getLastVideo() === "") {
318-
setCurrentSource(0);
319-
return player.next();
320-
}
321-
322-
currentVideoIndex = getLastVideoIndex();
323-
324-
if (main.configuration.ResumeLastVideo) {
325-
// TODO: Resume last (day/night) video when changing from day to night or vice versa
326-
}
327-
328-
setCurrentSource(currentVideoIndex);
329-
330-
player.next();
331-
}
289+
DayNightCycleController {
290+
id: dayNightCycleController
291+
enabled: main.configuration.DayNightCycleEnabled
292+
mode: main.configuration.DayNightCycleMode
293+
sunriseTime: main.configuration.DayNightCycleSunriseTime
294+
sunsetTime: main.configuration.DayNightCycleSunsetTime
295+
isLoading: main.isLoading
296+
onBeforeChanged: { main.save(); }
297+
onChanged: {
298+
videosConfig = getVideos();
299+
currentVideoIndex = resumeLastVideo ? getLastVideoIndex() : 0;
300+
setCurrentSource(currentVideoIndex);
301+
player.next();
332302
}
333303
}
334304

@@ -526,7 +496,6 @@ WallpaperItem {
526496
527497
Component.onCompleted: {
528498
startTimer.start();
529-
dayNightCycleTimer.start();
530499
Qt.callLater(() => {
531500
player.currentSource = Qt.binding(() => {
532501
return main.currentSource;
@@ -538,7 +507,7 @@ WallpaperItem {
538507
// Save last video and position to resume from it on next login/lock
539508
main.configuration.LastVideo = main.currentSource.filename;
540509
main.configuration.LastVideoPosition = player.lastVideoPosition;
541-
if(dayNightCycle) {
510+
if (main.configuration.DayNightCycleEnabled) {
542511
main.configuration[main.isDay ? "LastVideoDay" : "LastVideoNight"] = main.currentSource.filename;
543512
}
544513
main.configuration.writeConfig();

0 commit comments

Comments
 (0)