NSlider: now support label and description
- was a little tricky, got many crashed due to layout issue with Layout.fillWidth: true
This commit is contained in:
parent
5c9c61cf81
commit
d06679aad6
4 changed files with 180 additions and 197 deletions
|
|
@ -62,22 +62,18 @@ NLoader {
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: Style.marginSmall * scaling
|
spacing: Style.marginSmall * scaling
|
||||||
NText {
|
|
||||||
text: `${Math.round(Scaling.overrideScale * 100)}%`
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
|
||||||
}
|
|
||||||
NSlider {
|
NSlider {
|
||||||
id: scaleSlider
|
label: "Scaling"
|
||||||
from: 0.6
|
description: "Scaling goes brrrr"
|
||||||
to: 1.8
|
valueSuffix: "%"
|
||||||
stepSize: 0.01
|
from: 60
|
||||||
value: Scaling.overrideScale
|
to: 180
|
||||||
|
stepSize: 1
|
||||||
|
value: Scaling.overrideScale * 100
|
||||||
implicitWidth: bgRect.width * 0.75
|
implicitWidth: bgRect.width * 0.75
|
||||||
onMoved: {
|
onPressedChanged: function (pressed, value) {
|
||||||
Scaling.overrideScale = value
|
|
||||||
}
|
|
||||||
onPressedChanged: {
|
|
||||||
Scaling.overrideEnabled = true
|
Scaling.overrideEnabled = true
|
||||||
|
Scaling.overrideScale = value / 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NIconButton {
|
NIconButton {
|
||||||
|
|
@ -86,6 +82,7 @@ NLoader {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Scaling.overrideEnabled = false
|
Scaling.overrideEnabled = false
|
||||||
Scaling.overrideScale = 1.0
|
Scaling.overrideScale = 1.0
|
||||||
|
console.log("Reset!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import qs.Modules.Settings.Tabs as Tabs
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
|
|
||||||
NLoader {
|
NLoader {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,49 +116,19 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wallpaper Interval
|
// Wallpaper Interval
|
||||||
ColumnLayout {
|
NSlider {
|
||||||
spacing: 8
|
label: "Wallpaper Interval"
|
||||||
|
description: "How often to change wallpapers automatically (in seconds)"
|
||||||
|
valueSuffix: "s"
|
||||||
|
from: 10
|
||||||
|
to: 900
|
||||||
|
stepSize: 10
|
||||||
|
value: Settings.data.wallpaper.randomInterval
|
||||||
|
onPressedChanged: function (pressed, value) {
|
||||||
|
Settings.data.wallpaper.randomInterval = Math.round(value)
|
||||||
|
}
|
||||||
|
cutoutColor: Colors.backgroundPrimary
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Wallpaper Interval"
|
|
||||||
font.pointSize: 13
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Colors.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "How often to change wallpapers automatically (in seconds)"
|
|
||||||
font.pointSize: 12
|
|
||||||
color: Colors.textSecondary
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: Settings.data.wallpaper.randomInterval + " seconds"
|
|
||||||
font.pointSize: 13
|
|
||||||
color: Colors.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSlider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 10
|
|
||||||
to: 900
|
|
||||||
stepSize: 10
|
|
||||||
value: Settings.data.wallpaper.randomInterval
|
|
||||||
onPressedChanged: Settings.data.wallpaper.randomInterval = Math.round(value)
|
|
||||||
cutoutColor: Colors.backgroundPrimary
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,95 +229,35 @@ ColumnLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transition FPS
|
// Transition FPS
|
||||||
ColumnLayout {
|
NSlider {
|
||||||
spacing: 8
|
label: "Transition FPS"
|
||||||
|
description: "Frames per second for transition animations"
|
||||||
|
valueSuffix: " FPS"
|
||||||
|
from: 30
|
||||||
|
to: 500
|
||||||
|
stepSize: 5
|
||||||
|
value: Settings.data.wallpaper.swww.transitionFps
|
||||||
|
onPressedChanged: function (pressed, value) {
|
||||||
|
Settings.data.wallpaper.swww.transitionFps = Math.round(value)
|
||||||
|
}
|
||||||
|
cutoutColor: Colors.backgroundPrimary
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Transition FPS"
|
|
||||||
font.pointSize: 13
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Colors.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Frames per second for transition animations"
|
|
||||||
font.pointSize: 12
|
|
||||||
color: Colors.textSecondary
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: Settings.data.wallpaper.swww.transitionFps + " FPS"
|
|
||||||
font.pointSize: 13
|
|
||||||
color: Colors.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSlider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 30
|
|
||||||
to: 500
|
|
||||||
stepSize: 5
|
|
||||||
value: Settings.data.wallpaper.swww.transitionFps
|
|
||||||
onPressedChanged: Settings.data.wallpaper.swww.transitionFps = Math.round(value)
|
|
||||||
cutoutColor: Colors.backgroundPrimary
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transition Duration
|
// Transition Duration
|
||||||
ColumnLayout {
|
NSlider {
|
||||||
spacing: 8
|
label: "Transition Duration"
|
||||||
|
description: "Duration of transition animations in seconds"
|
||||||
|
valueSuffix: "s"
|
||||||
|
from: 0.25
|
||||||
|
to: 10
|
||||||
|
stepSize: 0.05
|
||||||
|
value: Settings.data.wallpaper.swww.transitionDuration
|
||||||
|
onPressedChanged: function (pressed, value) {
|
||||||
|
Settings.data.wallpaper.swww.transitionDuration = value
|
||||||
|
}
|
||||||
|
cutoutColor: Colors.backgroundPrimary
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Transition Duration"
|
|
||||||
font.pointSize: 13
|
|
||||||
font.weight: Style.fontWeightBold
|
|
||||||
color: Colors.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: "Duration of transition animations in seconds"
|
|
||||||
font.pointSize: 12
|
|
||||||
color: Colors.textSecondary
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
NText {
|
|
||||||
text: Settings.data.wallpaper.swww.transitionDuration.toFixed(3) + " seconds"
|
|
||||||
font.pointSize: 13
|
|
||||||
color: Colors.textPrimary
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSlider {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
from: 0.25
|
|
||||||
to: 10
|
|
||||||
stepSize: 0.05
|
|
||||||
value: Settings.data.wallpaper.swww.transitionDuration
|
|
||||||
onPressedChanged: Settings.data.wallpaper.swww.transitionDuration = value
|
|
||||||
cutoutColor: Colors.backgroundPrimary
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
|
import QtQuick.Layouts
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
Slider {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property real scaling: Scaling.scale(screen)
|
readonly property real scaling: Scaling.scale(screen)
|
||||||
|
|
@ -11,80 +12,156 @@ Slider {
|
||||||
readonly property real trackHeight: knobDiameter * 0.5
|
readonly property real trackHeight: knobDiameter * 0.5
|
||||||
readonly property real cutoutExtra: Style.baseWidgetSize * 0.1 * scaling
|
readonly property real cutoutExtra: Style.baseWidgetSize * 0.1 * scaling
|
||||||
|
|
||||||
|
property string label: ""
|
||||||
|
property string description: ""
|
||||||
|
property string valueSuffix: ""
|
||||||
|
property real from: 0.0
|
||||||
|
property real to: 1.0
|
||||||
|
property real stepSize: 0.01
|
||||||
|
property real value: 0.0
|
||||||
|
|
||||||
// Optional color to cut the track beneath the knob (should match surrounding background)
|
// Optional color to cut the track beneath the knob (should match surrounding background)
|
||||||
property var cutoutColor
|
property var cutoutColor
|
||||||
property var screen
|
property var screen
|
||||||
property bool snapAlways: true
|
property bool snapAlways: true
|
||||||
|
|
||||||
snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease
|
signal pressedChanged(bool pressed, real value)
|
||||||
implicitHeight: Math.max(trackHeight, knobDiameter)
|
signal moved(real value)
|
||||||
|
|
||||||
background: Rectangle {
|
Layout.fillWidth: true
|
||||||
x: root.leftPadding
|
spacing: Style.marginSmall * scaling
|
||||||
y: root.topPadding + root.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: Style.sliderWidth
|
|
||||||
implicitHeight: trackHeight
|
|
||||||
width: root.availableWidth
|
|
||||||
height: implicitHeight
|
|
||||||
radius: height / 2
|
|
||||||
color: Colors.surfaceVariant
|
|
||||||
|
|
||||||
Rectangle {
|
RowLayout {
|
||||||
id: activeTrack
|
Layout.fillWidth: true
|
||||||
width: root.visualPosition * parent.width
|
|
||||||
height: parent.height
|
ColumnLayout {
|
||||||
color: Colors.accentPrimary
|
spacing: Style.marginTiniest * scaling
|
||||||
radius: parent.radius
|
|
||||||
|
NText {
|
||||||
|
text: label
|
||||||
|
font.pointSize: Style.fontSizeMedium * scaling
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Colors.textPrimary
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
NText {
|
||||||
|
text: description
|
||||||
|
font.pointSize: Style.fontSizeSmall * scaling
|
||||||
|
color: Colors.textSecondary
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Circular cutout
|
NText {
|
||||||
Rectangle {
|
text: {
|
||||||
id: knobCutout
|
var v
|
||||||
width: knobDiameter + cutoutExtra
|
if (Number.isInteger(value)) {
|
||||||
height: knobDiameter + cutoutExtra
|
v = value
|
||||||
radius: width / 2
|
} else {
|
||||||
color: root.cutoutColor !== undefined ? root.cutoutColor : Colors.backgroundPrimary
|
v = value.toFixed(2)
|
||||||
x: Math.max(0, Math.min(parent.width - width,
|
}
|
||||||
root.visualPosition * (parent.width - root.knobDiameter) - cutoutExtra / 2))
|
|
||||||
y: (parent.height - height) / 2
|
if (valueSuffix != "") {
|
||||||
|
return v + valueSuffix
|
||||||
|
} else {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
font.pointSize: Style.fontSizeMedium * scaling
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Colors.textPrimary
|
||||||
|
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handle: Item {
|
Slider {
|
||||||
width: knob.implicitWidth
|
id: slider
|
||||||
height: knob.implicitHeight
|
|
||||||
x: root.leftPadding + root.visualPosition * (root.availableWidth - width)
|
|
||||||
y: root.topPadding + root.availableHeight / 2 - height / 2
|
|
||||||
|
|
||||||
// Subtle shadow for a more polished look (keeps theme colors)
|
Layout.fillWidth: true
|
||||||
MultiEffect {
|
from: root.from
|
||||||
anchors.fill: knob
|
to: root.to
|
||||||
source: knob
|
stepSize: root.stepSize
|
||||||
shadowEnabled: true
|
value: root.value
|
||||||
shadowColor: Colors.shadow
|
snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease
|
||||||
shadowOpacity: 0.25
|
implicitWidth: root.width
|
||||||
shadowHorizontalOffset: 0
|
implicitHeight: Math.max(trackHeight, knobDiameter)
|
||||||
shadowVerticalOffset: 1
|
onPressedChanged: {
|
||||||
shadowBlur: 8
|
root.pressedChanged(slider.pressed, slider.value)
|
||||||
|
}
|
||||||
|
onMoved: {
|
||||||
|
root.value = slider.value
|
||||||
|
root.moved(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
background: Rectangle {
|
||||||
id: knob
|
x: slider.leftPadding
|
||||||
implicitWidth: knobDiameter
|
y: slider.topPadding + slider.availableHeight / 2 - height / 2
|
||||||
implicitHeight: knobDiameter
|
implicitWidth: Style.sliderWidth
|
||||||
radius: width * 0.5
|
implicitHeight: trackHeight
|
||||||
color: root.pressed ? Colors.surfaceVariant : Colors.surface
|
width: slider.availableWidth
|
||||||
border.color: Colors.accentPrimary
|
height: implicitHeight
|
||||||
border.width: Math.max(1, Style.borderThick * scaling)
|
radius: height / 2
|
||||||
|
color: Colors.surfaceVariant
|
||||||
|
|
||||||
// Press feedback halo (using accent color, low opacity)
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.centerIn: parent
|
id: activeTrack
|
||||||
width: parent.width + 8 * scaling
|
width: slider.visualPosition * parent.width
|
||||||
height: parent.height + 8 * scaling
|
height: parent.height
|
||||||
radius: width / 2
|
|
||||||
color: Colors.accentPrimary
|
color: Colors.accentPrimary
|
||||||
opacity: root.pressed ? 0.16 : 0.0
|
radius: parent.radius
|
||||||
|
}
|
||||||
|
|
||||||
|
// Circular cutout
|
||||||
|
Rectangle {
|
||||||
|
id: knobCutout
|
||||||
|
width: knobDiameter + cutoutExtra
|
||||||
|
height: knobDiameter + cutoutExtra
|
||||||
|
radius: width / 2
|
||||||
|
color: slider.cutoutColor !== undefined ? slider.cutoutColor : Colors.backgroundPrimary
|
||||||
|
x: Math.max(0, Math.min(parent.width - width,
|
||||||
|
slider.visualPosition * (parent.width - knobDiameter) - cutoutExtra / 2))
|
||||||
|
y: (parent.height - height) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle: Item {
|
||||||
|
width: knob.implicitWidth
|
||||||
|
height: knob.implicitHeight
|
||||||
|
x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
|
||||||
|
y: slider.topPadding + slider.availableHeight / 2 - height / 2
|
||||||
|
|
||||||
|
// Subtle shadow for a more polished look (keeps theme colors)
|
||||||
|
MultiEffect {
|
||||||
|
anchors.fill: knob
|
||||||
|
source: knob
|
||||||
|
shadowEnabled: true
|
||||||
|
shadowColor: Colors.shadow
|
||||||
|
shadowOpacity: 0.25
|
||||||
|
shadowHorizontalOffset: 0
|
||||||
|
shadowVerticalOffset: 1
|
||||||
|
shadowBlur: 8
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: knob
|
||||||
|
implicitWidth: knobDiameter
|
||||||
|
implicitHeight: knobDiameter
|
||||||
|
radius: width * 0.5
|
||||||
|
color: slider.pressed ? Colors.surfaceVariant : Colors.surface
|
||||||
|
border.color: Colors.accentPrimary
|
||||||
|
border.width: Math.max(1, Style.borderThick * scaling)
|
||||||
|
|
||||||
|
// Press feedback halo (using accent color, low opacity)
|
||||||
|
Rectangle {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width + 8 * scaling
|
||||||
|
height: parent.height + 8 * scaling
|
||||||
|
radius: width / 2
|
||||||
|
color: Colors.accentPrimary
|
||||||
|
opacity: slider.pressed ? 0.16 : 0.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue