Files
noctalia-shell/Modules/Panels/Settings/Tabs/NotificationsTab.qml

326 lines
10 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Services.Compositor
import qs.Services.System
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
Layout.fillWidth: true
NHeader {
label: I18n.tr("settings.notifications.settings.section.label")
description: I18n.tr("settings.notifications.settings.section.description")
}
NToggle {
label: I18n.tr("settings.notifications.settings.enabled.label")
description: I18n.tr("settings.notifications.settings.enabled.description")
checked: Settings.data.notifications.enabled !== false
onToggled: checked => Settings.data.notifications.enabled = checked
}
NToggle {
label: I18n.tr("settings.notifications.settings.do-not-disturb.label")
description: I18n.tr("settings.notifications.settings.do-not-disturb.description")
checked: NotificationService.doNotDisturb
onToggled: checked => NotificationService.doNotDisturb = checked
}
NComboBox {
label: I18n.tr("settings.notifications.settings.location.label")
description: I18n.tr("settings.notifications.settings.location.description")
model: [
{
"key": "top",
"name": I18n.tr("options.launcher.position.top_center")
},
{
"key": "top_left",
"name": I18n.tr("options.launcher.position.top_left")
},
{
"key": "top_right",
"name": I18n.tr("options.launcher.position.top_right")
},
{
"key": "bottom",
"name": I18n.tr("options.launcher.position.bottom_center")
},
{
"key": "bottom_left",
"name": I18n.tr("options.launcher.position.bottom_left")
},
{
"key": "bottom_right",
"name": I18n.tr("options.launcher.position.bottom_right")
},
{
"key": "bar",
"name": I18n.tr("options.launcher.position.bar")
}
]
currentKey: Settings.data.notifications.location || "top_right"
onSelected: key => Settings.data.notifications.location = key
}
NToggle {
label: I18n.tr("settings.notifications.settings.always-on-top.label")
description: I18n.tr("settings.notifications.settings.always-on-top.description")
checked: Settings.data.notifications.overlayLayer
onToggled: checked => Settings.data.notifications.overlayLayer = checked
}
// Background Opacity
ColumnLayout {
spacing: Style.marginXXS
Layout.fillWidth: true
NLabel {
label: I18n.tr("settings.notifications.settings.background-opacity.label")
description: I18n.tr("settings.notifications.settings.background-opacity.description")
}
NValueSlider {
Layout.fillWidth: true
from: 0
to: 100
stepSize: 1
value: Settings.data.notifications.backgroundOpacity * 100
onMoved: value => Settings.data.notifications.backgroundOpacity = value / 100
text: Math.round(Settings.data.notifications.backgroundOpacity * 100) + "%"
}
}
// OSD settings moved to the dedicated OSD tab
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL
Layout.bottomMargin: Style.marginL
}
// Duration
ColumnLayout {
spacing: Style.marginL
Layout.fillWidth: true
NHeader {
label: I18n.tr("settings.notifications.duration.section.label")
description: I18n.tr("settings.notifications.duration.section.description")
}
// Respect Expire Timeout (eg. --expire-time flag in notify-send)
NToggle {
label: I18n.tr("settings.notifications.duration.respect-expire.label")
description: I18n.tr("settings.notifications.duration.respect-expire.description")
checked: Settings.data.notifications.respectExpireTimeout
onToggled: checked => Settings.data.notifications.respectExpireTimeout = checked
}
// Low Urgency Duration
ColumnLayout {
spacing: Style.marginXXS
Layout.fillWidth: true
NLabel {
label: I18n.tr("settings.notifications.duration.low-urgency.label")
description: I18n.tr("settings.notifications.duration.low-urgency.description")
}
RowLayout {
spacing: Style.marginL
Layout.fillWidth: true
NValueSlider {
Layout.fillWidth: true
from: 1
to: 30
stepSize: 1
value: Settings.data.notifications.lowUrgencyDuration
onMoved: value => Settings.data.notifications.lowUrgencyDuration = value
text: Settings.data.notifications.lowUrgencyDuration + "s"
}
// Reset button container
Item {
Layout.preferredWidth: 30 * Style.uiScaleRatio
Layout.preferredHeight: 30 * Style.uiScaleRatio
NIconButton {
icon: "refresh"
baseSize: Style.baseWidgetSize * 0.8
tooltipText: I18n.tr("settings.notifications.duration.reset")
onClicked: Settings.data.notifications.lowUrgencyDuration = 3
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
// Normal Urgency Duration
ColumnLayout {
spacing: Style.marginXXS
Layout.fillWidth: true
NLabel {
label: I18n.tr("settings.notifications.duration.normal-urgency.label")
description: I18n.tr("settings.notifications.duration.normal-urgency.description")
}
RowLayout {
spacing: Style.marginL
Layout.fillWidth: true
NValueSlider {
Layout.fillWidth: true
from: 1
to: 30
stepSize: 1
value: Settings.data.notifications.normalUrgencyDuration
onMoved: value => Settings.data.notifications.normalUrgencyDuration = value
text: Settings.data.notifications.normalUrgencyDuration + "s"
}
// Reset button container
Item {
Layout.preferredWidth: 30 * Style.uiScaleRatio
Layout.preferredHeight: 30 * Style.uiScaleRatio
NIconButton {
icon: "refresh"
baseSize: Style.baseWidgetSize * 0.8
tooltipText: I18n.tr("settings.notifications.duration.reset")
onClicked: Settings.data.notifications.normalUrgencyDuration = 8
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
// Critical Urgency Duration
ColumnLayout {
spacing: Style.marginXXS
Layout.fillWidth: true
NLabel {
label: I18n.tr("settings.notifications.duration.critical-urgency.label")
description: I18n.tr("settings.notifications.duration.critical-urgency.description")
}
RowLayout {
spacing: Style.marginL
Layout.fillWidth: true
NValueSlider {
Layout.fillWidth: true
from: 1
to: 30
stepSize: 1
value: Settings.data.notifications.criticalUrgencyDuration
onMoved: value => Settings.data.notifications.criticalUrgencyDuration = value
text: Settings.data.notifications.criticalUrgencyDuration + "s"
}
// Reset button container
Item {
Layout.preferredWidth: 30 * Style.uiScaleRatio
Layout.preferredHeight: 30 * Style.uiScaleRatio
NIconButton {
icon: "refresh"
baseSize: Style.baseWidgetSize * 0.8
tooltipText: I18n.tr("settings.notifications.duration.reset")
onClicked: Settings.data.notifications.criticalUrgencyDuration = 15
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL
Layout.bottomMargin: Style.marginL
}
// Monitor Configuration
NHeader {
label: I18n.tr("settings.notifications.monitors.section.label")
description: I18n.tr("settings.notifications.monitors.section.description")
}
Repeater {
model: Quickshell.screens || []
delegate: NCheckbox {
Layout.fillWidth: true
label: modelData.name || I18n.tr("system.unknown")
description: {
const compositorScale = CompositorService.getDisplayScale(modelData.name);
I18n.tr("system.monitor-description", {
"model": modelData.model,
"width": modelData.width * compositorScale,
"height": modelData.height * compositorScale,
"scale": compositorScale
});
}
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.marginL
Layout.bottomMargin: Style.marginL
}
// Toast Configuration
NHeader {
label: I18n.tr("settings.notifications.toast.section.label")
description: I18n.tr("settings.notifications.toast.section.description")
}
NToggle {
label: I18n.tr("settings.notifications.toast.keyboard.label")
description: I18n.tr("settings.notifications.toast.keyboard.description")
checked: Settings.data.notifications.enableKeyboardLayoutToast
onToggled: checked => Settings.data.notifications.enableKeyboardLayoutToast = checked
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginL
Layout.bottomMargin: Style.marginL
}
}