NValueSlider: new component + pimped NSlider with a small gradient and removed rounded corners due to issues.

This commit is contained in:
LemmyCook 2025-09-14 20:52:32 -04:00
parent 5ce5659b38
commit 5aa7ff7e91
14 changed files with 266 additions and 441 deletions

View file

@ -50,6 +50,7 @@ Item {
forceOpen: root.displayMode === "forceOpen" forceOpen: root.displayMode === "forceOpen"
forceClose: root.displayMode === "alwaysHide" forceClose: root.displayMode === "alwaysHide"
onClicked: { onClicked: {
// You could open keyboard settings here if needed // You could open keyboard settings here if needed
// For now, just show the current layout // For now, just show the current layout
} }

View file

@ -2,9 +2,9 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import qs.Widgets
import qs.Commons import qs.Commons
import qs.Services import qs.Services
import qs.Widgets
ColumnLayout { ColumnLayout {
id: root id: root
@ -34,37 +34,29 @@ ColumnLayout {
description: "System-wide volume level." description: "System-wide volume level."
} }
RowLayout { // Pipewire seems a bit finicky, if we spam too many volume changes it breaks easily
// Pipewire seems a bit finicky, if we spam too many volume changes it breaks easily // Probably because they have some quick fades in and out to avoid clipping
// Probably because they have some quick fades in and out to avoid clipping // We use a timer to space out the updates, to avoid lock up
// We use a timer to space out the updates, to avoid lock up Timer {
Timer { interval: Style.animationFast
interval: Style.animationFast running: true
running: true repeat: true
repeat: true onTriggered: {
onTriggered: { if (Math.abs(localVolume - AudioService.volume) >= 0.01) {
if (Math.abs(localVolume - AudioService.volume) >= 0.01) { AudioService.setVolume(localVolume)
AudioService.setVolume(localVolume)
}
} }
} }
}
NSlider { NValueSlider {
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
to: Settings.data.audio.volumeOverdrive ? 2.0 : 1.0 to: Settings.data.audio.volumeOverdrive ? 2.0 : 1.0
value: localVolume value: localVolume
stepSize: 0.01 stepSize: 0.01
onMoved: { text: Math.floor(AudioService.volume * 100) + "%"
localVolume = value onMoved: {
} localVolume = value
}
NText {
text: Math.floor(AudioService.volume * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
} }
} }
} }
@ -96,24 +88,14 @@ ColumnLayout {
description: "Microphone input volume level." description: "Microphone input volume level."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 1.0
to: 1.0 value: AudioService.inputVolume
value: AudioService.inputVolume stepSize: 0.01
stepSize: 0.01 text: Math.floor(AudioService.inputVolume * 100) + "%"
onMoved: { onMoved: value => AudioService.setInputVolume(value)
AudioService.setInputVolume(value)
}
}
NText {
text: Math.floor(AudioService.inputVolume * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
@ -144,9 +126,7 @@ ColumnLayout {
value: Settings.data.audio.volumeStep value: Settings.data.audio.volumeStep
stepSize: 1 stepSize: 1
suffix: "%" suffix: "%"
onValueChanged: { onValueChanged: value => Settings.data.audio.volumeStep = value
Settings.data.audio.volumeStep = value
}
} }
} }

View file

@ -82,23 +82,14 @@ ColumnLayout {
description: "Adjust the background opacity of the bar." description: "Adjust the background opacity of the bar."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 1
to: 1 stepSize: 0.01
stepSize: 0.01 value: Settings.data.bar.backgroundOpacity
value: Settings.data.bar.backgroundOpacity onMoved: value => Settings.data.bar.backgroundOpacity = value
onMoved: Settings.data.bar.backgroundOpacity = value text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.floor(Settings.data.bar.backgroundOpacity * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
NToggle { NToggle {
@ -133,25 +124,14 @@ ColumnLayout {
color: Color.mOnSurfaceVariant color: Color.mOnSurfaceVariant
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 1
to: 1 stepSize: 0.01
stepSize: 0.01 value: Settings.data.bar.marginVertical
value: Settings.data.bar.marginVertical onMoved: value => Settings.data.bar.marginVertical = value
onMoved: Settings.data.bar.marginVertical = value text: Math.round(Settings.data.bar.marginVertical * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.round(Settings.data.bar.marginVertical * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginXS * scaling
Layout.preferredWidth: 50
horizontalAlignment: Text.AlignRight
color: Color.mOnSurface
}
} }
} }
@ -164,25 +144,14 @@ ColumnLayout {
color: Color.mOnSurfaceVariant color: Color.mOnSurfaceVariant
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 1
to: 1 stepSize: 0.01
stepSize: 0.01 value: Settings.data.bar.marginHorizontal
value: Settings.data.bar.marginHorizontal onMoved: value => Settings.data.bar.marginHorizontal = value
onMoved: Settings.data.bar.marginHorizontal = value text: Math.round(Settings.data.bar.marginHorizontal * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.round(Settings.data.bar.marginHorizontal * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginXS * scaling
Layout.preferredWidth: 50
horizontalAlignment: Text.AlignRight
color: Color.mOnSurface
}
} }
} }
} }

View file

@ -116,21 +116,15 @@ ColumnLayout {
Layout.preferredWidth: 80 * scaling Layout.preferredWidth: 80 * scaling
} }
NSlider { NValueSlider {
id: scaleSlider id: scaleSlider
from: 0.7 from: 0.7
to: 1.8 to: 1.8
stepSize: 0.01 stepSize: 0.01
value: localScaling value: localScaling
onPressedChanged: ScalingService.setScreenScale(modelData, value) onPressedChanged: (pressed, value) => ScalingService.setScreenScale(modelData, value)
Layout.fillWidth: true
Layout.minimumWidth: 200 * scaling
}
NText {
text: `${Math.round(localScaling * 100)}%` text: `${Math.round(localScaling * 100)}%`
Layout.preferredWidth: 50 * scaling Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
} }
// Reset button container // Reset button container
@ -165,24 +159,14 @@ ColumnLayout {
Layout.preferredWidth: 80 * scaling Layout.preferredWidth: 80 * scaling
} }
NSlider { NValueSlider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.minimumWidth: 200 * scaling
from: 0 from: 0
to: 1 to: 1
value: brightnessMonitor ? brightnessMonitor.brightness : 0.5 value: brightnessMonitor ? brightnessMonitor.brightness : 0.5
stepSize: 0.05 stepSize: 0.01
onPressedChanged: { onPressedChanged: (pressed, value) => brightnessMonitor.setBrightness(value)
if (!pressed && brightnessMonitor) {
brightnessMonitor.setBrightness(value)
}
}
}
NText {
text: brightnessMonitor ? Math.round(brightnessMonitor.brightness * 100) + "%" : "N/A" text: brightnessMonitor ? Math.round(brightnessMonitor.brightness * 100) + "%" : "N/A"
Layout.preferredWidth: 50 * scaling
horizontalAlignment: Text.AlignRight
} }
// Empty container to match scale row layout // Empty container to match scale row layout

View file

@ -49,24 +49,14 @@ ColumnLayout {
label: "Background Opacity" label: "Background Opacity"
description: "Adjust the background opacity." description: "Adjust the background opacity."
} }
NValueSlider {
RowLayout { Layout.fillWidth: true
NSlider { from: 0
Layout.fillWidth: true to: 1
from: 0 stepSize: 0.01
to: 1 value: Settings.data.dock.backgroundOpacity
stepSize: 0.01 onMoved: value => Settings.data.dock.backgroundOpacity = value
value: Settings.data.dock.backgroundOpacity text: Math.floor(Settings.data.dock.backgroundOpacity * 100) + "%"
onMoved: Settings.data.dock.backgroundOpacity = value
cutoutColor: Color.mSurface
}
NText {
text: Math.floor(Settings.data.dock.backgroundOpacity * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
@ -79,23 +69,14 @@ ColumnLayout {
description: "Adjust the floating distance from the screen edge." description: "Adjust the floating distance from the screen edge."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 4
to: 4 stepSize: 0.01
stepSize: 0.01 value: Settings.data.dock.floatingRatio
value: Settings.data.dock.floatingRatio onMoved: value => Settings.data.dock.floatingRatio = value
onMoved: Settings.data.dock.floatingRatio = value text: Math.floor(Settings.data.dock.floatingRatio * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.floor(Settings.data.dock.floatingRatio * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }

View file

@ -74,23 +74,14 @@ ColumnLayout {
description: "Adjust the rounded border of all UI elements." description: "Adjust the rounded border of all UI elements."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 1
to: 1 stepSize: 0.01
stepSize: 0.01 value: Settings.data.general.radiusRatio
value: Settings.data.general.radiusRatio onMoved: value => Settings.data.general.radiusRatio = value
onMoved: Settings.data.general.radiusRatio = value text: Math.floor(Settings.data.general.radiusRatio * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.floor(Settings.data.general.radiusRatio * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
@ -104,23 +95,14 @@ ColumnLayout {
description: "Adjust global animation speed." description: "Adjust global animation speed."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0.1
from: 0.1 to: 2.0
to: 2.0 stepSize: 0.01
stepSize: 0.01 value: Settings.data.general.animationSpeed
value: Settings.data.general.animationSpeed onMoved: value => Settings.data.general.animationSpeed = value
onMoved: Settings.data.general.animationSpeed = value text: Math.round(Settings.data.general.animationSpeed * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.round(Settings.data.general.animationSpeed * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
} }
@ -156,23 +138,14 @@ ColumnLayout {
description: "Adjust the rounded corners of the screen." description: "Adjust the rounded corners of the screen."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 0
from: 0 to: 2
to: 2 stepSize: 0.01
stepSize: 0.01 value: Settings.data.general.screenRadiusRatio
value: Settings.data.general.screenRadiusRatio onMoved: value => Settings.data.general.screenRadiusRatio = value
onMoved: Settings.data.general.screenRadiusRatio = value text: Math.floor(Settings.data.general.screenRadiusRatio * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.floor(Settings.data.general.screenRadiusRatio * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
} }

View file

@ -74,24 +74,15 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
} }
RowLayout { NValueSlider {
NSlider { id: launcherBgOpacity
id: launcherBgOpacity Layout.fillWidth: true
Layout.fillWidth: true from: 0.0
from: 0.0 to: 1.0
to: 1.0 stepSize: 0.01
stepSize: 0.01 value: Settings.data.appLauncher.backgroundOpacity
value: Settings.data.appLauncher.backgroundOpacity onMoved: value => Settings.data.appLauncher.backgroundOpacity = value
onMoved: Settings.data.appLauncher.backgroundOpacity = value text: Math.floor(Settings.data.appLauncher.backgroundOpacity * 100) + "%"
cutoutColor: Color.mSurface
}
NText {
text: Math.floor(Settings.data.appLauncher.backgroundOpacity * 100) + "%"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }

View file

@ -100,23 +100,14 @@ ColumnLayout {
description: "How long low priority notifications stay visible." description: "How long low priority notifications stay visible."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 1
from: 1 to: 30
to: 30 stepSize: 1
stepSize: 1 value: Settings.data.notifications.lowUrgencyDuration
value: Settings.data.notifications.lowUrgencyDuration onMoved: value => Settings.data.notifications.lowUrgencyDuration = value
onMoved: Settings.data.notifications.lowUrgencyDuration = value text: Settings.data.notifications.lowUrgencyDuration + "s"
cutoutColor: Color.mSurface
}
NText {
text: Settings.data.notifications.lowUrgencyDuration + "s"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
@ -130,23 +121,14 @@ ColumnLayout {
description: "How long normal priority notifications stay visible." description: "How long normal priority notifications stay visible."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 1
from: 1 to: 30
to: 30 stepSize: 1
stepSize: 1 value: Settings.data.notifications.normalUrgencyDuration
value: Settings.data.notifications.normalUrgencyDuration onMoved: value => Settings.data.notifications.normalUrgencyDuration = value
onMoved: Settings.data.notifications.normalUrgencyDuration = value text: Settings.data.notifications.normalUrgencyDuration + "s"
cutoutColor: Color.mSurface
}
NText {
text: Settings.data.notifications.normalUrgencyDuration + "s"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
@ -160,23 +142,14 @@ ColumnLayout {
description: "How long critical priority notifications stay visible." description: "How long critical priority notifications stay visible."
} }
RowLayout { NValueSlider {
NSlider { Layout.fillWidth: true
Layout.fillWidth: true from: 1
from: 1 to: 30
to: 30 stepSize: 1
stepSize: 1 value: Settings.data.notifications.criticalUrgencyDuration
value: Settings.data.notifications.criticalUrgencyDuration onMoved: value => Settings.data.notifications.criticalUrgencyDuration = value
onMoved: Settings.data.notifications.criticalUrgencyDuration = value text: Settings.data.notifications.criticalUrgencyDuration + "s"
cutoutColor: Color.mSurface
}
NText {
text: Settings.data.notifications.criticalUrgencyDuration + "s"
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
color: Color.mOnSurface
}
} }
} }
} }

View file

@ -138,21 +138,14 @@ ColumnLayout {
description: "Duration of transition animations in seconds." description: "Duration of transition animations in seconds."
} }
RowLayout { NValueSlider {
spacing: Style.marginL * scaling Layout.fillWidth: true
NSlider { from: 500
Layout.fillWidth: true to: 10000
from: 500 stepSize: 100
to: 10000 value: Settings.data.wallpaper.transitionDuration
stepSize: 100 onMoved: value => Settings.data.wallpaper.transitionDuration = value
value: Settings.data.wallpaper.transitionDuration text: (Settings.data.wallpaper.transitionDuration / 1000).toFixed(1) + "s"
onMoved: Settings.data.wallpaper.transitionDuration = value
cutoutColor: Color.mSurface
}
NText {
text: (Settings.data.wallpaper.transitionDuration / 1000).toFixed(2) + "s"
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
}
} }
} }
@ -163,20 +156,13 @@ ColumnLayout {
description: "Duration of transition animations in seconds." description: "Duration of transition animations in seconds."
} }
RowLayout { NValueSlider {
spacing: Style.marginL * scaling Layout.fillWidth: true
NSlider { from: 0.0
Layout.fillWidth: true to: 1.0
from: 0.0 value: Settings.data.wallpaper.transitionEdgeSmoothness
to: 1.0 onMoved: value => Settings.data.wallpaper.transitionEdgeSmoothness = value
value: Settings.data.wallpaper.transitionEdgeSmoothness text: Math.round(Settings.data.wallpaper.transitionEdgeSmoothness * 100) + "%"
onMoved: Settings.data.wallpaper.transitionEdgeSmoothness = value
cutoutColor: Color.mSurface
}
NText {
text: Math.round(Settings.data.wallpaper.transitionEdgeSmoothness * 100) + "%"
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
}
} }
} }
} }

View file

@ -258,7 +258,6 @@ NBox {
stepSize: 0 stepSize: 0
snapAlways: false snapAlways: false
enabled: MediaService.trackLength > 0 && MediaService.canSeek enabled: MediaService.trackLength > 0 && MediaService.canSeek
cutoutColor: Color.mSurface
heightRatio: 0.65 heightRatio: 0.65
onMoved: { onMoved: {

View file

@ -243,24 +243,19 @@ Popup {
Layout.preferredWidth: 20 * scaling Layout.preferredWidth: 20 * scaling
} }
NSlider { NValueSlider {
id: redSlider id: redSlider
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
to: 255 to: 255
value: Math.round(root.selectedColor.r * 255) value: Math.round(root.selectedColor.r * 255)
onMoved: { onMoved: value => {
root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1) root.selectedColor = Qt.rgba(value / 255, root.selectedColor.g, root.selectedColor.b, 1)
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
root.currentHue = hsv[0] root.currentHue = hsv[0]
root.currentSaturation = hsv[1] root.currentSaturation = hsv[1]
} }
} text: Math.round(value)
NText {
text: Math.round(redSlider.value)
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 30 * scaling
} }
} }
@ -274,25 +269,20 @@ Popup {
Layout.preferredWidth: 20 * scaling Layout.preferredWidth: 20 * scaling
} }
NSlider { NValueSlider {
id: greenSlider id: greenSlider
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
to: 255 to: 255
value: Math.round(root.selectedColor.g * 255) value: Math.round(root.selectedColor.g * 255)
onMoved: { onMoved: value => {
root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1) root.selectedColor = Qt.rgba(root.selectedColor.r, value / 255, root.selectedColor.b, 1)
// Update stored hue and saturation when RGB changes // Update stored hue and saturation when RGB changes
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
root.currentHue = hsv[0] root.currentHue = hsv[0]
root.currentSaturation = hsv[1] root.currentSaturation = hsv[1]
} }
} text: Math.round(value)
NText {
text: Math.round(greenSlider.value)
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 30 * scaling
} }
} }
@ -306,25 +296,20 @@ Popup {
Layout.preferredWidth: 20 * scaling Layout.preferredWidth: 20 * scaling
} }
NSlider { NValueSlider {
id: blueSlider id: blueSlider
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
to: 255 to: 255
value: Math.round(root.selectedColor.b * 255) value: Math.round(root.selectedColor.b * 255)
onMoved: { onMoved: value => {
root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1) root.selectedColor = Qt.rgba(root.selectedColor.r, root.selectedColor.g, value / 255, 1)
// Update stored hue and saturation when RGB changes // Update stored hue and saturation when RGB changes
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
root.currentHue = hsv[0] root.currentHue = hsv[0]
root.currentSaturation = hsv[1] root.currentSaturation = hsv[1]
} }
} text: Math.round(value)
NText {
text: Math.round(blueSlider.value)
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 30 * scaling
} }
} }
@ -338,7 +323,7 @@ Popup {
Layout.preferredWidth: 80 * scaling Layout.preferredWidth: 80 * scaling
} }
NSlider { NValueSlider {
id: brightnessSlider id: brightnessSlider
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
@ -347,27 +332,22 @@ Popup {
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
return hsv[2] return hsv[2]
} }
onMoved: { onMoved: value => {
var hue = root.currentHue var hue = root.currentHue
var saturation = root.currentSaturation var saturation = root.currentSaturation
if (hue === 0 && saturation === 0) { if (hue === 0 && saturation === 0) {
var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255) var hsv = root.rgbToHsv(root.selectedColor.r * 255, root.selectedColor.g * 255, root.selectedColor.b * 255)
hue = hsv[0] hue = hsv[0]
saturation = hsv[1] saturation = hsv[1]
root.currentHue = hue root.currentHue = hue
root.currentSaturation = saturation root.currentSaturation = saturation
} }
var rgb = root.hsvToRgb(hue, saturation, value) var rgb = root.hsvToRgb(hue, saturation, value)
root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1) root.selectedColor = Qt.rgba(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1)
} }
}
NText {
text: Math.round(brightnessSlider.value) + "%" text: Math.round(brightnessSlider.value) + "%"
font.family: Settings.data.ui.fontFixed
Layout.preferredWidth: 40 * scaling
} }
} }
} }

View file

@ -7,13 +7,12 @@ import qs.Services
Slider { Slider {
id: root id: root
// Optional color to cut the track beneath the knob (should match surrounding background) property var cutoutColor: Color.mSurface
property var cutoutColor
property bool snapAlways: true property bool snapAlways: true
property real heightRatio: 0.75 property real heightRatio: 0.75
readonly property real knobDiameter: Math.round(Style.baseWidgetSize * heightRatio * scaling) readonly property real knobDiameter: Math.round(Style.baseWidgetSize * heightRatio * scaling)
readonly property real trackHeight: knobDiameter * 0.5 readonly property real trackHeight: knobDiameter * 0.4
readonly property real cutoutExtra: Math.round(Style.baseWidgetSize * 0.1 * scaling) readonly property real cutoutExtra: Math.round(Style.baseWidgetSize * 0.1 * scaling)
snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease
@ -26,15 +25,38 @@ Slider {
implicitHeight: trackHeight implicitHeight: trackHeight
width: root.availableWidth width: root.availableWidth
height: implicitHeight height: implicitHeight
radius: height / 2 radius: 0
color: Color.mSurface color: Color.mSurface
// Animated gradient active track
Rectangle { Rectangle {
id: activeTrack id: activeTrack
width: root.visualPosition * parent.width width: root.visualPosition * parent.width
height: parent.height height: parent.height
color: Color.mPrimary
radius: parent.radius radius: parent.radius
// Animated gradient fill
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop {
position: 0.0
color: Qt.darker(Color.mPrimary, 1.2)
Behavior on color { ColorAnimation { duration: 300 } }
}
GradientStop {
position: 0.5
color: Color.mPrimary
SequentialAnimation on position {
loops: Animation.Infinite
NumberAnimation { from: 0.3; to: 0.7; duration: 2000; easing.type: Easing.InOutSine }
NumberAnimation { from: 0.7; to: 0.3; duration: 2000; easing.type: Easing.InOutSine }
}
}
GradientStop {
position: 1.0
color: Qt.lighter(Color.mPrimary, 1.2)
}
}
} }
// Circular cutout // Circular cutout
@ -44,8 +66,7 @@ Slider {
height: knobDiameter + cutoutExtra height: knobDiameter + cutoutExtra
radius: width / 2 radius: width / 2
color: root.cutoutColor !== undefined ? root.cutoutColor : Color.mSurface color: root.cutoutColor !== undefined ? root.cutoutColor : Color.mSurface
x: Math.max(0, Math.min(parent.width - width, Math.round(root.visualPosition * (parent.width - root.knobDiameter) - cutoutExtra / 2))) x: root.leftPadding + root.visualPosition * (root.availableWidth - root.knobDiameter) - cutoutExtra / 2
y: (parent.height - height) / 2
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
@ -73,4 +94,4 @@ Slider {
} }
} }
} }
} }

View file

@ -1,61 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Services
import qs.Widgets
RowLayout {
id: root
// Properties that mirror NSlider
property real from: 0
property real to: 1
property real value: 0
property real stepSize: 0.01
property var cutoutColor
property bool snapAlways: true
property real heightRatio: 0.75
property bool showPercentage: true
property string suffix: "%"
property int decimalPlaces: 0 // 0 for integers, 1 for one decimal place, etc.
// Signals
signal moved(real value)
signal pressedChanged(bool pressed)
spacing: Style.marginS * scaling
NSlider {
id: slider
Layout.fillWidth: true
from: root.from
to: root.to
value: root.value
stepSize: root.stepSize
cutoutColor: root.cutoutColor
snapAlways: root.snapAlways
heightRatio: root.heightRatio
stableWidth: true
minWidth: 200 * scaling
onMoved: root.moved(value)
onPressedChanged: root.pressedChanged(pressed)
}
NText {
id: percentageLabel
visible: root.showPercentage
text: {
if (root.decimalPlaces === 0) {
return Math.round(slider.value * 100) + root.suffix
} else {
return (slider.value * 100).toFixed(root.decimalPlaces) + root.suffix
}
}
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: Style.marginS * scaling
Layout.preferredWidth: 50 * scaling
horizontalAlignment: Text.AlignRight
}
}

48
Widgets/NValueSlider.qml Normal file
View file

@ -0,0 +1,48 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Services
import qs.Widgets
RowLayout {
id: root
property real from: 0
property real to: 1
property real value: 0
property real stepSize: 0.01
property var cutoutColor: Color.mSurface
property bool snapAlways: true
property real heightRatio: 0.75
property string text: ""
// Signals
signal moved(real value)
signal pressedChanged(bool pressed, real value)
spacing: Style.marginL * scaling
NSlider {
id: slider
Layout.fillWidth: true
from: root.from
to: root.to
value: root.value
stepSize: root.stepSize
cutoutColor: root.cutoutColor
snapAlways: root.snapAlways
heightRatio: root.heightRatio
onMoved: root.moved(value)
onPressedChanged: root.pressedChanged(pressed, value)
}
NText {
visible: root.text !== ""
text: root.text
font.family: Settings.data.ui.fontFixed
Layout.alignment: Qt.AlignVCenter
Layout.preferredWidth: 40 * scaling
horizontalAlignment: Text.AlignRight
}
}