SettingsTabs: use NHeader, move display settings around
This commit is contained in:
parent
0d611fc891
commit
7594651e05
19 changed files with 483 additions and 480 deletions
|
|
@ -106,6 +106,7 @@ Singleton {
|
||||||
"settings-wallpaper-selector": "library-photo",
|
"settings-wallpaper-selector": "library-photo",
|
||||||
"settings-screen-recorder": "video",
|
"settings-screen-recorder": "video",
|
||||||
"settings-hooks": "link",
|
"settings-hooks": "link",
|
||||||
|
"settings-notification": "notification",
|
||||||
"settings-about": "info-square-rounded",
|
"settings-about": "info-square-rounded",
|
||||||
"bluetooth": "bluetooth",
|
"bluetooth": "bluetooth",
|
||||||
"bt-device-generic": "bluetooth",
|
"bt-device-generic": "bluetooth",
|
||||||
|
|
|
||||||
|
|
@ -399,6 +399,10 @@ Singleton {
|
||||||
property list<string> monitors: []
|
property list<string> monitors: []
|
||||||
// Last time the user opened the notification history (ms since epoch)
|
// Last time the user opened the notification history (ms since epoch)
|
||||||
property real lastSeenTs: 0
|
property real lastSeenTs: 0
|
||||||
|
// Duration settings for different urgency levels (in seconds)
|
||||||
|
property int lowUrgencyDuration: 3
|
||||||
|
property int normalUrgencyDuration: 8
|
||||||
|
property int criticalUrgencyDuration: 15
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio
|
// audio
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,11 @@ NPanel {
|
||||||
Dock,
|
Dock,
|
||||||
Hooks,
|
Hooks,
|
||||||
Launcher,
|
Launcher,
|
||||||
Brightness,
|
|
||||||
ColorScheme,
|
ColorScheme,
|
||||||
Display,
|
Display,
|
||||||
General,
|
General,
|
||||||
Network,
|
Network,
|
||||||
|
Notification,
|
||||||
ScreenRecorder,
|
ScreenRecorder,
|
||||||
Weather,
|
Weather,
|
||||||
Wallpaper,
|
Wallpaper,
|
||||||
|
|
@ -72,10 +72,6 @@ NPanel {
|
||||||
id: audioTab
|
id: audioTab
|
||||||
Tabs.AudioTab {}
|
Tabs.AudioTab {}
|
||||||
}
|
}
|
||||||
Component {
|
|
||||||
id: brightnessTab
|
|
||||||
Tabs.BrightnessTab {}
|
|
||||||
}
|
|
||||||
Component {
|
Component {
|
||||||
id: displayTab
|
id: displayTab
|
||||||
Tabs.DisplayTab {}
|
Tabs.DisplayTab {}
|
||||||
|
|
@ -116,6 +112,10 @@ NPanel {
|
||||||
id: dockTab
|
id: dockTab
|
||||||
Tabs.DockTab {}
|
Tabs.DockTab {}
|
||||||
}
|
}
|
||||||
|
Component {
|
||||||
|
id: notificationTab
|
||||||
|
Tabs.NotificationTab {}
|
||||||
|
}
|
||||||
|
|
||||||
// Order *DOES* matter
|
// Order *DOES* matter
|
||||||
function updateTabsModel() {
|
function updateTabsModel() {
|
||||||
|
|
@ -149,16 +149,16 @@ NPanel {
|
||||||
"label": "Display",
|
"label": "Display",
|
||||||
"icon": "settings-display",
|
"icon": "settings-display",
|
||||||
"source": displayTab
|
"source": displayTab
|
||||||
|
}, {
|
||||||
|
"id": SettingsPanel.Tab.Notification,
|
||||||
|
"label": "Notification",
|
||||||
|
"icon": "settings-notification",
|
||||||
|
"source": notificationTab
|
||||||
}, {
|
}, {
|
||||||
"id": SettingsPanel.Tab.Network,
|
"id": SettingsPanel.Tab.Network,
|
||||||
"label": "Network",
|
"label": "Network",
|
||||||
"icon": "settings-network",
|
"icon": "settings-network",
|
||||||
"source": networkTab
|
"source": networkTab
|
||||||
}, {
|
|
||||||
"id": SettingsPanel.Tab.Brightness,
|
|
||||||
"label": "Brightness",
|
|
||||||
"icon": "settings-brightness",
|
|
||||||
"source": brightnessTab
|
|
||||||
}, {
|
}, {
|
||||||
"id": SettingsPanel.Tab.Weather,
|
"id": SettingsPanel.Tab.Weather,
|
||||||
"label": "Weather",
|
"label": "Weather",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ import qs.Services
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Audio Settings"
|
||||||
|
description: "Configure system audio, devices, and media player preferences."
|
||||||
|
}
|
||||||
|
|
||||||
property real localVolume: AudioService.volume
|
property real localVolume: AudioService.volume
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
|
@ -158,12 +163,8 @@ ColumnLayout {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginS * scaling
|
spacing: Style.marginS * scaling
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Audio Devices"
|
title: "Audio Devices"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
|
|
@ -234,12 +235,8 @@ ColumnLayout {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Media Player"
|
title: "Media Player"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred player
|
// Preferred player
|
||||||
|
|
@ -360,12 +357,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginS * scaling
|
spacing: Style.marginS * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Audio Visualizer"
|
title: "Audio Visualizer"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AudioService Visualizer section
|
// AudioService Visualizer section
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
import qs.Commons
|
import qs.Commons
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
@ -9,6 +10,24 @@ import qs.Modules.SettingsPanel.Bar
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Bar Settings"
|
||||||
|
description: "Configure bar appearance, positioning, and monitor settings."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions to update arrays immutably
|
||||||
|
function addMonitor(list, name) {
|
||||||
|
const arr = (list || []).slice()
|
||||||
|
if (!arr.includes(name))
|
||||||
|
arr.push(name)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
function removeMonitor(list, name) {
|
||||||
|
return (list || []).filter(function (n) {
|
||||||
|
return n !== name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Handler for drag start - disables panel background clicks
|
// Handler for drag start - disables panel background clicks
|
||||||
function handleDragStart() {
|
function handleDragStart() {
|
||||||
var panel = PanelService.getPanel("settingsPanel")
|
var panel = PanelService.getPanel("settingsPanel")
|
||||||
|
|
@ -56,23 +75,19 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginXXS * scaling
|
spacing: Style.marginXXS * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Background Opacity"
|
title: "Background Opacity"
|
||||||
font.pointSize: Style.fontSizeL * scaling
|
description: "Adjust the background opacity of the bar."
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mOnSurface
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Adjust the background opacity of the bar."
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|
@ -189,25 +204,49 @@ ColumnLayout {
|
||||||
Layout.bottomMargin: Style.marginXL * scaling
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Monitor Configuration
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Monitor Configuration"
|
||||||
|
description: "Choose which monitors should display the bar."
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Quickshell.screens || []
|
||||||
|
delegate: NCheckbox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}`
|
||||||
|
description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||||
|
checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1
|
||||||
|
onToggled: checked => {
|
||||||
|
if (checked) {
|
||||||
|
Settings.data.bar.monitors = addMonitor(Settings.data.bar.monitors, modelData.name)
|
||||||
|
} else {
|
||||||
|
Settings.data.bar.monitors = removeMonitor(Settings.data.bar.monitors, modelData.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
// Widgets Management Section
|
// Widgets Management Section
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginXXS * scaling
|
spacing: Style.marginXXS * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Widgets Positioning"
|
title: "Widgets Positioning"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
description: "Drag and drop widgets to reorder them within each section, or use the add/remove buttons to manage widgets."
|
||||||
font.weight: Style.fontWeightBold
|
bottomMargin: 0
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Drag and drop widgets to reorder them within each section, or use the add/remove buttons to manage widgets."
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bar Sections
|
// Bar Sections
|
||||||
|
|
|
||||||
|
|
@ -1,340 +0,0 @@
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
import qs.Commons
|
|
||||||
import qs.Services
|
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
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
|
|
||||||
|
|
||||||
// Brightness Step Section
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: Style.marginS * scaling
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
NSpinBox {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
label: "Brightness Step Size"
|
|
||||||
description: "Adjust the step size for brightness changes (scroll wheel, keyboard shortcuts)."
|
|
||||||
minimum: 1
|
|
||||||
maximum: 50
|
|
||||||
value: Settings.data.brightness.brightnessStep
|
|
||||||
stepSize: 1
|
|
||||||
suffix: "%"
|
|
||||||
onValueChanged: {
|
|
||||||
Settings.data.brightness.brightnessStep = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Monitor Overview Section
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: Style.marginL * scaling
|
|
||||||
|
|
||||||
NLabel {
|
|
||||||
label: "Monitors Brightness Control"
|
|
||||||
description: "Current brightness levels for all detected monitors."
|
|
||||||
}
|
|
||||||
|
|
||||||
// Single monitor display using the same data source as the bar icon
|
|
||||||
Repeater {
|
|
||||||
model: BrightnessService.monitors
|
|
||||||
Rectangle {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
radius: Style.radiusM * scaling
|
|
||||||
color: Color.mSurface
|
|
||||||
border.color: Color.mOutline
|
|
||||||
border.width: Math.max(1, Style.borderS * scaling)
|
|
||||||
implicitHeight: contentCol.implicitHeight + Style.marginXL * 2 * scaling
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: contentCol
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: Style.marginL * scaling
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: `${model.modelData.name} [${model.modelData.model}]`
|
|
||||||
font.pointSize: Style.fontSizeL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: model.method
|
|
||||||
font.pointSize: Style.fontSizeXS * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
spacing: Style.marginM * scaling
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Brightness:"
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurface
|
|
||||||
}
|
|
||||||
|
|
||||||
NSlider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 0
|
|
||||||
to: 1
|
|
||||||
value: model.brightness
|
|
||||||
stepSize: 0.05
|
|
||||||
onPressedChanged: {
|
|
||||||
if (!pressed) {
|
|
||||||
var monitor = BrightnessService.getMonitorForScreen(model.modelData)
|
|
||||||
monitor.setBrightness(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: Math.round(model.brightness * 100) + "%"
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mPrimary
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NDivider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 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
|
|
||||||
Settings.data.nightLight.forced = 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 && !Settings.data.nightLight.forced
|
|
||||||
|
|
||||||
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
|
|
||||||
minimumWidth: 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
|
|
||||||
minimumWidth: 120 * scaling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force activation toggle
|
|
||||||
NToggle {
|
|
||||||
label: "Force activation"
|
|
||||||
description: "Immediately apply night temperature without scheduling or fade."
|
|
||||||
checked: Settings.data.nightLight.forced
|
|
||||||
onToggled: checked => {
|
|
||||||
Settings.data.nightLight.forced = checked
|
|
||||||
if (checked && !Settings.data.nightLight.enabled) {
|
|
||||||
// Ensure enabled when forcing
|
|
||||||
wlsunsetCheck.running = true
|
|
||||||
} else {
|
|
||||||
NightLightService.apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visible: Settings.data.nightLight.enabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,6 +10,11 @@ ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Color Schemes"
|
||||||
|
description: "Choose and customize color schemes for your interface."
|
||||||
|
}
|
||||||
|
|
||||||
// Cache for scheme JSON (can be flat or {dark, light})
|
// Cache for scheme JSON (can be flat or {dark, light})
|
||||||
property var schemeColorsCache: ({})
|
property var schemeColorsCache: ({})
|
||||||
|
|
||||||
|
|
@ -151,19 +156,9 @@ ColumnLayout {
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginM * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Predefined Color Schemes"
|
title: "Predefined Color Schemes"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
description: "To use these color schemes, you must turn off Matugen. With Matugen enabled, colors are automatically generated from your wallpaper."
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "To use these color schemes, you must turn off Matugen. With Matugen enabled, colors are automatically generated from your wallpaper."
|
|
||||||
font.pointSize: Style.fontSizeM * scaling
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
Layout.fillWidth: true
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color Schemes Grid
|
// Color Schemes Grid
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
import qs.Commons
|
import qs.Commons
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
@ -10,6 +11,24 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
width: root.width
|
width: root.width
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Dock Settings"
|
||||||
|
description: "Configure dock behavior, appearance, and monitor settings."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions to update arrays immutably
|
||||||
|
function addMonitor(list, name) {
|
||||||
|
const arr = (list || []).slice()
|
||||||
|
if (!arr.includes(name))
|
||||||
|
arr.push(name)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
function removeMonitor(list, name) {
|
||||||
|
return (list || []).filter(function (n) {
|
||||||
|
return n !== name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
label: "Auto-hide"
|
label: "Auto-hide"
|
||||||
description: "Automatically hide when not in use."
|
description: "Automatically hide when not in use."
|
||||||
|
|
@ -24,12 +43,52 @@ ColumnLayout {
|
||||||
onToggled: checked => Settings.data.dock.exclusive = checked
|
onToggled: checked => Settings.data.dock.exclusive = checked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor Configuration
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginXXS * scaling
|
spacing: Style.marginXXS * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NLabel {
|
NHeader {
|
||||||
label: "Background Opacity"
|
title: "Monitor Configuration"
|
||||||
|
description: "Choose which monitors should display the dock."
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Quickshell.screens || []
|
||||||
|
delegate: NCheckbox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}`
|
||||||
|
description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||||
|
checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1
|
||||||
|
onToggled: checked => {
|
||||||
|
if (checked) {
|
||||||
|
Settings.data.dock.monitors = addMonitor(Settings.data.dock.monitors, modelData.name)
|
||||||
|
} else {
|
||||||
|
Settings.data.dock.monitors = removeMonitor(Settings.data.dock.monitors, modelData.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Background Opacity"
|
||||||
description: "Adjust the background opacity."
|
description: "Adjust the background opacity."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,12 +112,18 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginXXS * scaling
|
spacing: Style.marginXXS * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NLabel {
|
NHeader {
|
||||||
label: "Dock Floating Distance"
|
title: "Dock Floating Distance"
|
||||||
description: "Adjust the floating distance from the screen edge."
|
description: "Adjust the floating distance from the screen edge."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Profile"
|
||||||
|
description: "Configure your user profile and avatar settings."
|
||||||
|
}
|
||||||
|
|
||||||
// Profile section
|
// Profile section
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -48,12 +53,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "User Interface"
|
title: "User Interface"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
|
|
@ -133,12 +134,8 @@ ColumnLayout {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
NText {
|
NHeader {
|
||||||
text: "Screen Corners"
|
title: "Screen Corners"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
|
|
@ -187,12 +184,8 @@ ColumnLayout {
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
NText {
|
NHeader {
|
||||||
text: "Fonts"
|
title: "Fonts"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Font configuration section
|
// Font configuration section
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
width: root.width
|
width: root.width
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "System Hooks"
|
||||||
|
description: "Configure commands to be executed when system events occur."
|
||||||
|
}
|
||||||
|
|
||||||
// Enable/Disable Toggle
|
// Enable/Disable Toggle
|
||||||
NToggle {
|
NToggle {
|
||||||
label: "Enable Hooks"
|
label: "Enable Hooks"
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Launcher Settings"
|
||||||
|
description: "Configure the application launcher panel behavior and appearance."
|
||||||
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Network Settings"
|
||||||
|
description: "Configure Wi-Fi and Bluetooth connectivity options."
|
||||||
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
label: "Enable Wi-Fi"
|
label: "Enable Wi-Fi"
|
||||||
description: "Enable Wi-Fi connectivity."
|
description: "Enable Wi-Fi connectivity."
|
||||||
|
|
|
||||||
182
Modules/SettingsPanel/Tabs/NotificationTab.qml
Normal file
182
Modules/SettingsPanel/Tabs/NotificationTab.qml
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
import Quickshell
|
||||||
|
import qs.Commons
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// Helper functions to update arrays immutably
|
||||||
|
function addMonitor(list, name) {
|
||||||
|
const arr = (list || []).slice()
|
||||||
|
if (!arr.includes(name))
|
||||||
|
arr.push(name)
|
||||||
|
return arr
|
||||||
|
}
|
||||||
|
function removeMonitor(list, name) {
|
||||||
|
return (list || []).filter(function (n) {
|
||||||
|
return n !== name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// General Notification Settings
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginL * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "General Settings"
|
||||||
|
}
|
||||||
|
|
||||||
|
NToggle {
|
||||||
|
label: "Do Not Disturb"
|
||||||
|
description: "Disable all notification popups when enabled."
|
||||||
|
checked: Settings.data.notifications.doNotDisturb
|
||||||
|
onToggled: checked => Settings.data.notifications.doNotDisturb = checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor Configuration
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Monitor Configuration"
|
||||||
|
description: "Choose which monitors should display notifications."
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Quickshell.screens || []
|
||||||
|
delegate: NCheckbox {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
label: `${modelData.name || "Unknown"}${modelData.model ? `: ${modelData.model}` : ""}`
|
||||||
|
description: `${modelData.width}x${modelData.height} at (${modelData.x}, ${modelData.y})`
|
||||||
|
checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1
|
||||||
|
onToggled: checked => {
|
||||||
|
if (checked) {
|
||||||
|
Settings.data.notifications.monitors = addMonitor(Settings.data.notifications.monitors, modelData.name)
|
||||||
|
} else {
|
||||||
|
Settings.data.notifications.monitors = removeMonitor(Settings.data.notifications.monitors, modelData.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NDivider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: Style.marginXL * scaling
|
||||||
|
Layout.bottomMargin: Style.marginXL * scaling
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notification Duration Settings
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginL * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Notification Duration"
|
||||||
|
description: "Configure how long notifications stay visible based on their urgency level."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Low Urgency Duration
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NLabel {
|
||||||
|
label: "Low Urgency Duration"
|
||||||
|
description: "How long low priority notifications stay visible."
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
NSlider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
from: 1
|
||||||
|
to: 30
|
||||||
|
stepSize: 1
|
||||||
|
value: Settings.data.notifications.lowUrgencyDuration
|
||||||
|
onMoved: Settings.data.notifications.lowUrgencyDuration = value
|
||||||
|
cutoutColor: Color.mSurface
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: Settings.data.notifications.lowUrgencyDuration + "s"
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.leftMargin: Style.marginS * scaling
|
||||||
|
color: Color.mOnSurface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal Urgency Duration
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NLabel {
|
||||||
|
label: "Normal Urgency Duration"
|
||||||
|
description: "How long normal priority notifications stay visible."
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
NSlider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
from: 1
|
||||||
|
to: 30
|
||||||
|
stepSize: 1
|
||||||
|
value: Settings.data.notifications.normalUrgencyDuration
|
||||||
|
onMoved: Settings.data.notifications.normalUrgencyDuration = value
|
||||||
|
cutoutColor: Color.mSurface
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: Settings.data.notifications.normalUrgencyDuration + "s"
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.leftMargin: Style.marginS * scaling
|
||||||
|
color: Color.mOnSurface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Critical Urgency Duration
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NLabel {
|
||||||
|
label: "Critical Urgency Duration"
|
||||||
|
description: "How long critical priority notifications stay visible."
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
NSlider {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
from: 1
|
||||||
|
to: 30
|
||||||
|
stepSize: 1
|
||||||
|
value: Settings.data.notifications.criticalUrgencyDuration
|
||||||
|
onMoved: Settings.data.notifications.criticalUrgencyDuration = value
|
||||||
|
cutoutColor: Color.mSurface
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: Settings.data.notifications.criticalUrgencyDuration + "s"
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.leftMargin: Style.marginS * scaling
|
||||||
|
color: Color.mOnSurface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,11 @@ ColumnLayout {
|
||||||
|
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Screen Recorder"
|
||||||
|
description: "Configure screen recording settings and output options."
|
||||||
|
}
|
||||||
|
|
||||||
// Output Directory
|
// Output Directory
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: Style.marginS * scaling
|
spacing: Style.marginS * scaling
|
||||||
|
|
@ -53,12 +58,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Video Settings"
|
title: "Video Settings"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source
|
// Source
|
||||||
|
|
@ -203,12 +204,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Audio Settings"
|
title: "Audio Settings"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
Layout.bottomMargin: Style.marginS * scaling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio Source
|
// Audio Source
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ ColumnLayout {
|
||||||
|
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Wallpaper Selector"
|
||||||
|
description: "Browse and select wallpapers from your configured directory."
|
||||||
|
}
|
||||||
|
|
||||||
property list<string> wallpapersList: []
|
property list<string> wallpapersList: []
|
||||||
property string currentWallpaper: ""
|
property string currentWallpaper: ""
|
||||||
|
|
||||||
|
|
@ -42,11 +47,8 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current wallpaper display
|
// Current wallpaper display
|
||||||
NText {
|
NHeader {
|
||||||
text: "Current Wallpaper"
|
title: "Current Wallpaper"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
@ -80,18 +82,9 @@ ColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
// Wallpaper grid
|
// Wallpaper grid
|
||||||
NText {
|
NHeader {
|
||||||
text: "Wallpaper Selector"
|
title: "Wallpaper Selector"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
description: "Click on a wallpaper to set it as your current wallpaper."
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Click on a wallpaper to set it as your current wallpaper."
|
|
||||||
color: Color.mOnSurfaceVariant
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Wallpaper Management"
|
||||||
|
description: "Configure wallpaper settings, automation, and appearance options."
|
||||||
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
label: "Enable Wallpaper Management"
|
label: "Enable Wallpaper Management"
|
||||||
description: "Manage wallpapers with Noctalia. (Uncheck if you prefer using another application)."
|
description: "Manage wallpapers with Noctalia. (Uncheck if you prefer using another application)."
|
||||||
|
|
@ -89,11 +94,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Look & Feel"
|
title: "Look & Feel"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill Mode
|
// Fill Mode
|
||||||
|
|
@ -189,11 +191,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginL * scaling
|
spacing: Style.marginL * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Automation"
|
title: "Automation"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Random Wallpaper
|
// Random Wallpaper
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
NHeader {
|
||||||
|
title: "Weather & Location"
|
||||||
|
description: "Configure weather display and location settings."
|
||||||
|
}
|
||||||
|
|
||||||
// Location section
|
// Location section
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
@ -57,11 +62,8 @@ ColumnLayout {
|
||||||
spacing: Style.marginM * scaling
|
spacing: Style.marginM * scaling
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
NText {
|
NHeader {
|
||||||
text: "Weather"
|
title: "Weather"
|
||||||
font.pointSize: Style.fontSizeXXL * scaling
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Color.mSecondary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NToggle {
|
NToggle {
|
||||||
|
|
|
||||||
|
|
@ -87,9 +87,26 @@ Singleton {
|
||||||
// Maximum visible notifications
|
// Maximum visible notifications
|
||||||
property int maxVisible: 5
|
property int maxVisible: 5
|
||||||
|
|
||||||
|
// Function to get duration based on urgency
|
||||||
|
function getDurationForUrgency(urgency) {
|
||||||
|
switch (urgency) {
|
||||||
|
case 0:
|
||||||
|
// Low urgency
|
||||||
|
return (Settings.data.notifications.lowUrgencyDuration || 3) * 1000
|
||||||
|
case 1:
|
||||||
|
// Normal urgency
|
||||||
|
return (Settings.data.notifications.normalUrgencyDuration || 8) * 1000
|
||||||
|
case 2:
|
||||||
|
// Critical urgency
|
||||||
|
return (Settings.data.notifications.criticalUrgencyDuration || 15) * 1000
|
||||||
|
default:
|
||||||
|
return (Settings.data.notifications.normalUrgencyDuration || 8) * 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Auto-hide timer
|
// Auto-hide timer
|
||||||
property Timer hideTimer: Timer {
|
property Timer hideTimer: Timer {
|
||||||
interval: 8000 // 8 seconds - longer display time
|
interval: 1000 // Check every second
|
||||||
repeat: true
|
repeat: true
|
||||||
running: notificationModel.count > 0
|
running: notificationModel.count > 0
|
||||||
|
|
||||||
|
|
@ -98,11 +115,26 @@ Singleton {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the oldest notification (last in the list)
|
// Check each notification for expiration
|
||||||
let oldestNotification = notificationModel.get(notificationModel.count - 1).rawNotification
|
for (var i = notificationModel.count - 1; i >= 0; i--) {
|
||||||
if (oldestNotification) {
|
let notificationData = notificationModel.get(i)
|
||||||
// Trigger animation signal instead of direct dismiss
|
if (notificationData && notificationData.rawNotification) {
|
||||||
animateAndRemove(oldestNotification, notificationModel.count - 1)
|
let notification = notificationData.rawNotification
|
||||||
|
let urgency = notificationData.urgency
|
||||||
|
let timestamp = notificationData.timestamp
|
||||||
|
|
||||||
|
// Calculate if this notification should be removed
|
||||||
|
let duration = getDurationForUrgency(urgency)
|
||||||
|
let now = new Date()
|
||||||
|
let elapsed = now.getTime() - timestamp.getTime()
|
||||||
|
|
||||||
|
if (elapsed >= duration) {
|
||||||
|
// Trigger animation signal instead of direct dismiss
|
||||||
|
animateAndRemove(notification, i)
|
||||||
|
break
|
||||||
|
// Only remove one notification per check to avoid conflicts
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
Widgets/NHeader.qml
Normal file
33
Widgets/NHeader.qml
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Commons
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string title: ""
|
||||||
|
property string description: ""
|
||||||
|
property real bottomMargin: Style.marginL * scaling
|
||||||
|
|
||||||
|
spacing: Style.marginXXS * scaling
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: root.title
|
||||||
|
font.pointSize: Style.fontSizeXXL * scaling
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Color.mSecondary
|
||||||
|
Layout.bottomMargin: Style.marginS * scaling
|
||||||
|
visible: root.title !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: root.description
|
||||||
|
font.pointSize: Style.fontSizeM * scaling
|
||||||
|
color: Color.mOnSurfaceVariant
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.bottomMargin: root.bottomMargin
|
||||||
|
visible: root.description !== ""
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue