NightLight: moved from DisplayTab to BrightnessTab
This commit is contained in:
parent
f1c9ed9caa
commit
459bb59dd5
3 changed files with 204 additions and 213 deletions
|
|
@ -68,7 +68,9 @@ Variants {
|
||||||
// Make the overview darker
|
// Make the overview darker
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: Settings.data.colorSchemes.darkMode ? Qt.rgba(Color.mSurface.r, Color.mSurface.g, Color.mSurface.b, 0.5) : Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.5)
|
color: Settings.data.colorSchemes.darkMode ? Qt.rgba(Color.mSurface.r, Color.mSurface.g, Color.mSurface.b,
|
||||||
|
0.5) : Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g,
|
||||||
|
Color.mOnSurface.b, 0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
import qs.Commons
|
import qs.Commons
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
@ -9,6 +10,45 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
// Time dropdown options (00:00 .. 23:30)
|
||||||
|
ListModel {
|
||||||
|
id: timeOptions
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var h = 0; h < 24; h++) {
|
||||||
|
for (var m = 0; m < 60; m += 30) {
|
||||||
|
var hh = ("0" + h).slice(-2)
|
||||||
|
var mm = ("0" + m).slice(-2)
|
||||||
|
var key = hh + ":" + mm
|
||||||
|
timeOptions.append({
|
||||||
|
"key": key,
|
||||||
|
"name": key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for wlsunset availability when enabling Night Light
|
||||||
|
Process {
|
||||||
|
id: wlsunsetCheck
|
||||||
|
command: ["which", "wlsunset"]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
onExited: function (exitCode) {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
Settings.data.nightLight.enabled = true
|
||||||
|
NightLightService.apply()
|
||||||
|
ToastService.showNotice("Night Light", "Enabled")
|
||||||
|
} else {
|
||||||
|
Settings.data.nightLight.enabled = false
|
||||||
|
ToastService.showWarning("Night Light", "wlsunset not installed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout: StdioCollector {}
|
||||||
|
stderr: StdioCollector {}
|
||||||
|
}
|
||||||
|
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
|
||||||
// Brightness Step Section
|
// Brightness Step Section
|
||||||
|
|
@ -122,4 +162,165 @@ ColumnLayout {
|
||||||
Layout.topMargin: Style.marginXL * scaling
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
Layout.bottomMargin: Style.marginXL * scaling
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Night Light Section
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Night Light"
|
||||||
|
font.pointSize: Style.fontSizeXXL * scaling
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Color.mSecondary
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Reduce blue light emission to help you sleep better and reduce eye strain."
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
color: Color.mOnSurfaceVariant
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NToggle {
|
||||||
|
label: "Enable Night Light"
|
||||||
|
description: "Apply a warm color filter to reduce blue light emission."
|
||||||
|
checked: Settings.data.nightLight.enabled
|
||||||
|
onToggled: checked => {
|
||||||
|
if (checked) {
|
||||||
|
// Verify wlsunset exists before enabling
|
||||||
|
wlsunsetCheck.running = true
|
||||||
|
} else {
|
||||||
|
Settings.data.nightLight.enabled = false
|
||||||
|
NightLightService.apply()
|
||||||
|
ToastService.showNotice("Night Light", "Disabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temperature
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXS * scaling
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
NLabel {
|
||||||
|
label: "Color temperature"
|
||||||
|
description: "Choose two temperatures in Kelvin."
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
visible: Settings.data.nightLight.enabled
|
||||||
|
spacing: Style.marginM * scaling
|
||||||
|
Layout.fillWidth: false
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Night"
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
color: Color.mOnSurfaceVariant
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
NTextInput {
|
||||||
|
text: Settings.data.nightLight.nightTemp
|
||||||
|
inputMethodHints: Qt.ImhDigitsOnly
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
onEditingFinished: {
|
||||||
|
var nightTemp = parseInt(text)
|
||||||
|
var dayTemp = parseInt(Settings.data.nightLight.dayTemp)
|
||||||
|
if (!isNaN(nightTemp) && !isNaN(dayTemp)) {
|
||||||
|
// Clamp value between [1000 .. (dayTemp-500)]
|
||||||
|
var clampedValue = Math.min(dayTemp - 500, Math.max(1000, nightTemp))
|
||||||
|
text = Settings.data.nightLight.nightTemp = clampedValue.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Day"
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
color: Color.mOnSurfaceVariant
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
}
|
||||||
|
NTextInput {
|
||||||
|
text: Settings.data.nightLight.dayTemp
|
||||||
|
inputMethodHints: Qt.ImhDigitsOnly
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
onEditingFinished: {
|
||||||
|
var dayTemp = parseInt(text)
|
||||||
|
var nightTemp = parseInt(Settings.data.nightLight.nightTemp)
|
||||||
|
if (!isNaN(nightTemp) && !isNaN(dayTemp)) {
|
||||||
|
// Clamp value between [(nightTemp+500) .. 6500]
|
||||||
|
var clampedValue = Math.max(nightTemp + 500, Math.min(6500, dayTemp))
|
||||||
|
text = Settings.data.nightLight.dayTemp = clampedValue.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NToggle {
|
||||||
|
label: "Automatic Scheduling"
|
||||||
|
description: `Based on the sunset and sunrise time in <i>${LocationService.stableName}</i> - recommended.`
|
||||||
|
checked: Settings.data.nightLight.autoSchedule
|
||||||
|
onToggled: checked => Settings.data.nightLight.autoSchedule = checked
|
||||||
|
visible: Settings.data.nightLight.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule settings
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXS * scaling
|
||||||
|
visible: Settings.data.nightLight.enabled && !Settings.data.nightLight.autoSchedule
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: false
|
||||||
|
spacing: Style.marginM * scaling
|
||||||
|
|
||||||
|
NLabel {
|
||||||
|
label: "Manual Scheduling"
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {// add a little more spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Sunrise Time"
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
color: Color.mOnSurfaceVariant
|
||||||
|
}
|
||||||
|
|
||||||
|
NComboBox {
|
||||||
|
model: timeOptions
|
||||||
|
currentKey: Settings.data.nightLight.manualSunrise
|
||||||
|
placeholder: "Select start time"
|
||||||
|
onSelected: key => {
|
||||||
|
Settings.data.nightLight.manualSunrise = key
|
||||||
|
}
|
||||||
|
preferredWidth: 120 * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {// add a little more spacing
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: "Sunset Time"
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
color: Color.mOnSurfaceVariant
|
||||||
|
}
|
||||||
|
NComboBox {
|
||||||
|
model: timeOptions
|
||||||
|
currentKey: Settings.data.nightLight.manualSunset
|
||||||
|
placeholder: "Select stop time"
|
||||||
|
onSelected: key => {
|
||||||
|
Settings.data.nightLight.manualSunset = key
|
||||||
|
}
|
||||||
|
preferredWidth: 120 * scaling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
|
||||||
import qs.Commons
|
import qs.Commons
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
@ -10,45 +9,6 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
// Time dropdown options (00:00 .. 23:30)
|
|
||||||
ListModel {
|
|
||||||
id: timeOptions
|
|
||||||
}
|
|
||||||
Component.onCompleted: {
|
|
||||||
for (var h = 0; h < 24; h++) {
|
|
||||||
for (var m = 0; m < 60; m += 30) {
|
|
||||||
var hh = ("0" + h).slice(-2)
|
|
||||||
var mm = ("0" + m).slice(-2)
|
|
||||||
var key = hh + ":" + mm
|
|
||||||
timeOptions.append({
|
|
||||||
"key": key,
|
|
||||||
"name": key
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for wlsunset availability when enabling Night Light
|
|
||||||
Process {
|
|
||||||
id: wlsunsetCheck
|
|
||||||
command: ["which", "wlsunset"]
|
|
||||||
running: false
|
|
||||||
|
|
||||||
onExited: function (exitCode) {
|
|
||||||
if (exitCode === 0) {
|
|
||||||
Settings.data.nightLight.enabled = true
|
|
||||||
NightLightService.apply()
|
|
||||||
ToastService.showNotice("Night Light", "Enabled")
|
|
||||||
} else {
|
|
||||||
Settings.data.nightLight.enabled = false
|
|
||||||
ToastService.showWarning("Night Light", "wlsunset not installed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout: StdioCollector {}
|
|
||||||
stderr: StdioCollector {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper functions to update arrays immutably
|
// Helper functions to update arrays immutably
|
||||||
function addMonitor(list, name) {
|
function addMonitor(list, name) {
|
||||||
const arr = (list || []).slice()
|
const arr = (list || []).slice()
|
||||||
|
|
@ -221,177 +181,5 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NDivider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: Style.marginXL * scaling
|
|
||||||
Layout.bottomMargin: Style.marginXL * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
// Night Light Section
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: Style.marginXS * scaling
|
|
||||||
NText {
|
|
||||||
text: "Night Light"
|
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Reduce blue light emission to help you sleep better and reduce eye strain."
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NToggle {
|
|
||||||
label: "Enable Night Light"
|
|
||||||
description: "Apply a warm color filter to reduce blue light emission."
|
|
||||||
checked: Settings.data.nightLight.enabled
|
|
||||||
onToggled: checked => {
|
|
||||||
if (checked) {
|
|
||||||
// Verify wlsunset exists before enabling
|
|
||||||
wlsunsetCheck.running = true
|
|
||||||
} else {
|
|
||||||
Settings.data.nightLight.enabled = false
|
|
||||||
NightLightService.apply()
|
|
||||||
ToastService.showNotice("Night Light", "Disabled")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temperature
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: Style.marginXS * scaling
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
|
|
||||||
NLabel {
|
|
||||||
label: "Color temperature"
|
|
||||||
description: "Choose two temperatures in Kelvin."
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
visible: Settings.data.nightLight.enabled
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
Layout.fillWidth: false
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Night"
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
|
|
||||||
NTextInput {
|
|
||||||
text: Settings.data.nightLight.nightTemp
|
|
||||||
inputMethodHints: Qt.ImhDigitsOnly
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
onEditingFinished: {
|
|
||||||
var nightTemp = parseInt(text)
|
|
||||||
var dayTemp = parseInt(Settings.data.nightLight.dayTemp)
|
|
||||||
if (!isNaN(nightTemp) && !isNaN(dayTemp)) {
|
|
||||||
// Clamp value between [1000 .. (dayTemp-500)]
|
|
||||||
var clampedValue = Math.min(dayTemp - 500, Math.max(1000, nightTemp))
|
|
||||||
text = Settings.data.nightLight.nightTemp = clampedValue.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Day"
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
NTextInput {
|
|
||||||
text: Settings.data.nightLight.dayTemp
|
|
||||||
inputMethodHints: Qt.ImhDigitsOnly
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
onEditingFinished: {
|
|
||||||
var dayTemp = parseInt(text)
|
|
||||||
var nightTemp = parseInt(Settings.data.nightLight.nightTemp)
|
|
||||||
if (!isNaN(nightTemp) && !isNaN(dayTemp)) {
|
|
||||||
// Clamp value between [(nightTemp+500) .. 6500]
|
|
||||||
var clampedValue = Math.max(nightTemp + 500, Math.min(6500, dayTemp))
|
|
||||||
text = Settings.data.nightLight.dayTemp = clampedValue.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NToggle {
|
|
||||||
label: "Automatic Scheduling"
|
|
||||||
description: `Based on the sunset and sunrise time in <i>${LocationService.stableName}</i> - recommended.`
|
|
||||||
checked: Settings.data.nightLight.autoSchedule
|
|
||||||
onToggled: checked => Settings.data.nightLight.autoSchedule = checked
|
|
||||||
visible: Settings.data.nightLight.enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schedule settings
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: Style.marginXS * scaling
|
|
||||||
visible: Settings.data.nightLight.enabled && !Settings.data.nightLight.autoSchedule
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: false
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
|
|
||||||
NLabel {
|
|
||||||
label: "Manual Scheduling"
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {// add a little more spacing
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Sunrise Time"
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
}
|
|
||||||
|
|
||||||
NComboBox {
|
|
||||||
model: timeOptions
|
|
||||||
currentKey: Settings.data.nightLight.manualSunrise
|
|
||||||
placeholder: "Select start time"
|
|
||||||
onSelected: key => {
|
|
||||||
Settings.data.nightLight.manualSunrise = key
|
|
||||||
}
|
|
||||||
preferredWidth: 120 * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {// add a little more spacing
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Sunset Time"
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
}
|
|
||||||
NComboBox {
|
|
||||||
model: timeOptions
|
|
||||||
currentKey: Settings.data.nightLight.manualSunset
|
|
||||||
placeholder: "Select stop time"
|
|
||||||
onSelected: key => {
|
|
||||||
Settings.data.nightLight.manualSunset = key
|
|
||||||
}
|
|
||||||
preferredWidth: 120 * scaling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NDivider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: Style.marginXL * scaling
|
|
||||||
Layout.bottomMargin: Style.marginXL * scaling
|
|
||||||
visible: Settings.data.nightLight.enabled
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue