Merge branch 'dev' of github.com:Ly-sec/Noctalia into dev

This commit is contained in:
quadbyte 2025-08-08 08:24:35 -04:00
commit 54b531586a
6 changed files with 97 additions and 103 deletions

View file

@ -0,0 +1,45 @@
import QtQuick
import QtQuick.Controls
import qs.Settings
// Reusable themed slider styled like the sliders in Wallpaper.qml
Slider {
id: slider
// Optional monitor screen for scaling context
property var screen
// Convenience flag mirroring Wallpaper sliders
property bool snapAlways: true
snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease
background: Rectangle {
x: slider.leftPadding
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4 * Theme.scale(screen)
width: slider.availableWidth
height: implicitHeight
radius: height / 2
color: Theme.surfaceVariant
Rectangle {
width: slider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: parent.radius
}
}
handle: Rectangle {
x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 20 * Theme.scale(screen)
implicitHeight: 20 * Theme.scale(screen)
radius: width / 2
color: slider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2 * Theme.scale(screen)
}
}

View file

@ -7,6 +7,8 @@ import qs.Settings
ColumnLayout {
id: root
property var screen
property string label: ""
property string description: ""
property bool value: false

View file

@ -82,6 +82,7 @@ Singleton {
property var barMonitors: [] // Array of monitor names to show the bar on
property var dockMonitors: [] // Array of monitor names to show the dock on
property var notificationMonitors: [] // Array of monitor names to show notifications on, "*" means all monitors
property var monitorScaleOverrides: {} // Map of monitor name -> scale override (e.g., 0.8..2.0). When set, Theme.scale() returns this value
}
}

View file

@ -13,7 +13,16 @@ Singleton {
// Automatic scaling based on screen width
function scale(currentScreen) {
if (currentScreen.width != 0) {
// Per-monitor override from settings
try {
const overrides = Settings.settings.monitorScaleOverrides || {};
if (currentScreen && currentScreen.name && overrides[currentScreen.name] !== undefined) {
return overrides[currentScreen.name];
}
} catch (e) {
// ignore
}
if (currentScreen && currentScreen.width != 0) {
var ratio = currentScreen.width / designScreenWidth;
// Limit the final scale range between [0.8...2]
return Math.max(0.8, Math.min(2.0, ratio));

View file

@ -4,6 +4,7 @@ import QtQuick.Layouts
import Quickshell
import qs.Components
import qs.Settings
import qs.Components
ColumnLayout {
id: root
@ -417,6 +418,38 @@ ColumnLayout {
Settings.settings.notificationMonitors = monitors;
}
}
// Scale slider
ColumnLayout {
Layout.fillWidth: true
spacing: 4 * Theme.scale(screen)
Text { text: "Scale"; color: Theme.textSecondary; font.pixelSize: 10 * Theme.scale(screen) }
RowLayout {
Layout.fillWidth: true
spacing: 8 * Theme.scale(screen)
// Value read from settings override, default to Theme.scale(modelData)
property real currentValue: (Settings.settings.monitorScaleOverrides && Settings.settings.monitorScaleOverrides[monitorCard.monitorName] !== undefined) ? Settings.settings.monitorScaleOverrides[monitorCard.monitorName] : Theme.scale(modelData)
// Reusable slider component (exact style from Wallpaper.qml)
ThemedSlider {
id: scaleSlider
Layout.fillWidth: true
screen: modelData
from: 0.8
to: 2.0
stepSize: 0.05
snapAlways: true
value: parent.currentValue
onValueChanged: {
let overrides = Settings.settings.monitorScaleOverrides || {};
overrides = Object.assign({}, overrides);
overrides[monitorCard.monitorName] = value;
Settings.settings.monitorScaleOverrides = overrides;
parent.currentValue = value;
}
}
Text { text: parent.currentValue.toFixed(2); font.pixelSize: 12 * Theme.scale(screen); color: Theme.textPrimary; width: 36 }
}
}
}
}
}

View file

@ -197,49 +197,17 @@ ColumnLayout {
}
Slider {
ThemedSlider {
id: intervalSlider
Layout.fillWidth: true
from: 10
to: 900
stepSize: 10
value: Settings.settings.wallpaperInterval
snapMode: Slider.SnapAlways
snapAlways: true
onMoved: {
Settings.settings.wallpaperInterval = Math.round(value);
}
background: Rectangle {
x: intervalSlider.leftPadding
y: intervalSlider.topPadding + intervalSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: intervalSlider.availableWidth
height: implicitHeight
radius: 2
color: Theme.surfaceVariant
Rectangle {
width: intervalSlider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: 2
}
}
handle: Rectangle {
x: intervalSlider.leftPadding + intervalSlider.visualPosition * (intervalSlider.availableWidth - width)
y: intervalSlider.topPadding + intervalSlider.availableHeight / 2 - height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: intervalSlider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2
}
}
}
@ -529,49 +497,17 @@ ColumnLayout {
}
Slider {
ThemedSlider {
id: fpsSlider
Layout.fillWidth: true
from: 30
to: 500
stepSize: 5
value: Settings.settings.transitionFps
snapMode: Slider.SnapAlways
snapAlways: true
onMoved: {
Settings.settings.transitionFps = Math.round(value);
}
background: Rectangle {
x: fpsSlider.leftPadding
y: fpsSlider.topPadding + fpsSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: fpsSlider.availableWidth
height: implicitHeight
radius: 2
color: Theme.surfaceVariant
Rectangle {
width: fpsSlider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: 2
}
}
handle: Rectangle {
x: fpsSlider.leftPadding + fpsSlider.visualPosition * (fpsSlider.availableWidth - width)
y: fpsSlider.topPadding + fpsSlider.availableHeight / 2 - height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: fpsSlider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2
}
}
}
@ -612,49 +548,17 @@ ColumnLayout {
}
Slider {
ThemedSlider {
id: durationSlider
Layout.fillWidth: true
from: 0.25
to: 10
stepSize: 0.05
value: Settings.settings.transitionDuration
snapMode: Slider.SnapAlways
snapAlways: true
onMoved: {
Settings.settings.transitionDuration = value;
}
background: Rectangle {
x: durationSlider.leftPadding
y: durationSlider.topPadding + durationSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: 4
width: durationSlider.availableWidth
height: implicitHeight
radius: 2
color: Theme.surfaceVariant
Rectangle {
width: durationSlider.visualPosition * parent.width
height: parent.height
color: Theme.accentPrimary
radius: 2
}
}
handle: Rectangle {
x: durationSlider.leftPadding + durationSlider.visualPosition * (durationSlider.availableWidth - width)
y: durationSlider.topPadding + durationSlider.availableHeight / 2 - height / 2
implicitWidth: 20
implicitHeight: 20
radius: 10
color: durationSlider.pressed ? Theme.surfaceVariant : Theme.surface
border.color: Theme.accentPrimary
border.width: 2
}
}
}