NTextInput: improved layout and adapted calling code all over the shell.

This commit is contained in:
LemmyCook 2025-08-28 12:22:42 -04:00
parent e86e7344f3
commit 3f4cec1719
8 changed files with 106 additions and 105 deletions

View file

@ -301,6 +301,7 @@ NPanel {
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
padding: Style.marginL * scaling
clip: true
Loader {
active: true

View file

@ -216,8 +216,6 @@ ColumnLayout {
}
// Preferred player (persistent)
NTextInput {
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
label: "Preferred Player"
description: "Substring to match MPRIS player (identity/bus/desktop)."
placeholderText: "e.g. spotify, vlc, mpv"
@ -239,8 +237,6 @@ ColumnLayout {
NTextInput {
id: blacklistInput
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
label: "Blacklist player"
description: "Substring, e.g. plex, shim, mpv."
placeholderText: "type substring and press +"

View file

@ -74,7 +74,6 @@ ColumnLayout {
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.preferredWidth: parent.width - (Style.marginL * 2 * scaling)
}
ColumnLayout {
@ -253,7 +252,6 @@ ColumnLayout {
color: Color.mOnSurfaceVariant
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.preferredWidth: parent.width - (Style.marginL * 2 * scaling)
}
}
@ -278,7 +276,7 @@ ColumnLayout {
visible: Settings.data.nightLight.enabled
NLabel {
label: "Intensity"
description: "Higher values create warmer light."
description: "Higher values create warmer tones."
}
RowLayout {
spacing: Style.marginS * scaling
@ -305,46 +303,61 @@ ColumnLayout {
}
}
// Temperature settings (inline like schedule)
RowLayout {
visible: Settings.data.nightLight.enabled
Layout.fillWidth: false
spacing: Style.marginM * scaling
NText {
text: "Low"
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
// Temperature
ColumnLayout {
spacing: Style.marginXS * scaling
Layout.alignment: Qt.AlignVCenter
NLabel {
label: "Color temperature"
description: "Select two temperatures in Kelvin"
}
NTextInput {
text: Settings.data.nightLight.lowTemp.toString()
inputMethodHints: Qt.ImhDigitsOnly
Layout.preferredWidth: 100 * scaling
onEditingFinished: {
var v = parseInt(text)
if (!isNaN(v)) {
Settings.data.nightLight.lowTemp = Math.max(1000, Math.min(6500, v))
NightLightService.apply()
RowLayout {
visible: Settings.data.nightLight.enabled
spacing: Style.marginM * scaling
Layout.fillWidth: false
Layout.fillHeight: true
Layout.alignment: Qt.AlignVCenter
NText {
text: "Low"
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
Layout.alignment: Qt.AlignVCenter
}
NTextInput {
text: Settings.data.nightLight.lowTemp.toString()
inputMethodHints: Qt.ImhDigitsOnly
Layout.alignment: Qt.AlignVCenter
onEditingFinished: {
var v = parseInt(text)
if (!isNaN(v)) {
Settings.data.nightLight.lowTemp = Math.max(1000, Math.min(6500, v))
NightLightService.apply()
}
}
}
}
Item {}
Item {}
NText {
text: "High"
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
}
NTextInput {
text: Settings.data.nightLight.highTemp.toString()
inputMethodHints: Qt.ImhDigitsOnly
Layout.preferredWidth: 100 * scaling
onEditingFinished: {
var v = parseInt(text)
if (!isNaN(v)) {
Settings.data.nightLight.highTemp = Math.max(1000, Math.min(10000, v))
NightLightService.apply()
NText {
text: "High"
font.pointSize: Style.fontSizeM * scaling
color: Color.mOnSurfaceVariant
Layout.alignment: Qt.AlignVCenter
}
NTextInput {
text: Settings.data.nightLight.highTemp.toString()
inputMethodHints: Qt.ImhDigitsOnly
Layout.alignment: Qt.AlignVCenter
onEditingFinished: {
var v = parseInt(text)
if (!isNaN(v)) {
Settings.data.nightLight.highTemp = Math.max(1000, Math.min(10000, v))
NightLightService.apply()
}
}
}
}

View file

@ -25,10 +25,9 @@ ColumnLayout {
NTextInput {
label: "Profile Picture"
description: "Your profile picture displayed in various places throughout the shell."
description: "Your profile picture that appears throughout the interface."
text: Settings.data.general.avatarImage
placeholderText: "/home/user/.face"
Layout.fillWidth: true
onEditingFinished: {
Settings.data.general.avatarImage = text
}

View file

@ -24,7 +24,8 @@ ColumnLayout {
onEditingFinished: {
Settings.data.screenRecorder.directory = text
}
Layout.fillWidth: true
Layout.maximumWidth: 420 * scaling
}
ColumnLayout {

View file

@ -10,6 +10,7 @@ ColumnLayout {
// Location section
RowLayout {
Layout.fillWidth: true
spacing: Style.marginL * scaling
NTextInput {
@ -25,6 +26,7 @@ ColumnLayout {
LocationService.resetWeather()
}
}
Layout.maximumWidth: 420 * scaling
}
NText {

View file

@ -35,10 +35,10 @@ ColumnLayout {
label: "Wallpaper Directory"
description: "Path to your wallpaper directory."
text: Settings.data.wallpaper.directory
Layout.fillWidth: true
onEditingFinished: {
Settings.data.wallpaper.directory = text
}
Layout.maximumWidth: 420 * scaling
}
NDivider {
@ -79,12 +79,7 @@ ColumnLayout {
NText {
// Show friendly H:MM format from current settings
text: {
const s = Settings.data.wallpaper.randomInterval
const h = Math.floor(s / 3600)
const m = Math.floor((s % 3600) / 60)
return (h > 0 ? (h + "h ") : "") + (m > 0 ? (m + "m") : (h === 0 ? "0m" : ""))
}
text: Time.formatVagueHumanReadableDuration(Settings.data.wallpaper.randomInterval)
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
}
}
@ -284,14 +279,15 @@ ColumnLayout {
NTextInput {
label: "Custom Interval"
description: "Enter time as HH:MM (e.g., 1:30)."
description: "Enter time as HH:MM (e.g., 01:30)."
inputMaxWidth: 100 * scaling
text: {
const s = Settings.data.wallpaper.randomInterval
const h = Math.floor(s / 3600)
const m = Math.floor((s % 3600) / 60)
return h + ":" + (m < 10 ? ("0" + m) : m)
}
Layout.fillWidth: true
onEditingFinished: {
const m = text.trim().match(/^(\d{1,2}):(\d{2})$/)
if (m) {

View file

@ -4,13 +4,14 @@ import QtQuick.Layouts
import qs.Commons
import qs.Services
Item {
ColumnLayout {
id: root
property string label: ""
property string description: ""
property bool readOnly: false
property bool enabled: true
property int inputMaxWidth: 420 * scaling
property alias text: input.text
property alias placeholderText: input.placeholderText
@ -18,61 +19,53 @@ Item {
signal editingFinished
// Sizing
implicitWidth: Style.sliderWidth * 1.6 * scaling
implicitHeight: Style.baseWidgetSize * 2.75 * scaling
spacing: Style.marginS * scaling
implicitHeight: frame.height
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NLabel {
label: root.label
description: root.description
visible: root.label !== "" || root.description !== ""
}
NLabel {
label: root.label
description: root.description
// Container
Rectangle {
id: frame
implicitWidth: parent.width
implicitHeight: Style.baseWidgetSize * 1.1 * scaling
Layout.minimumWidth: 80 * scaling
Layout.maximumWidth: root.inputMaxWidth
radius: Style.radiusM * scaling
color: Color.mSurface
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
// Focus ring
Rectangle {
anchors.fill: parent
radius: frame.radius
color: Color.transparent
border.color: input.activeFocus ? Color.mSecondary : Color.transparent
border.width: input.activeFocus ? Math.max(1, Style.borderS * scaling) : 0
}
// Container
Rectangle {
id: frame
Layout.topMargin: Style.marginXS * scaling
implicitWidth: root.width
implicitHeight: Style.baseWidgetSize * 1.35 * scaling
radius: Style.radiusM * scaling
color: Color.mSurface
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
RowLayout {
anchors.fill: parent
anchors.leftMargin: Style.marginM * scaling
anchors.rightMargin: Style.marginM * scaling
spacing: Style.marginS * scaling
// Focus ring
Rectangle {
anchors.fill: parent
radius: frame.radius
color: Color.transparent
border.color: input.activeFocus ? Color.mSecondary : Color.transparent
border.width: input.activeFocus ? Math.max(1, Style.borderS * scaling) : 0
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: Style.marginM * scaling
anchors.rightMargin: Style.marginM * scaling
spacing: Style.marginS * scaling
// Optional leading icon slot in the future
// Item { Layout.preferredWidth: 0 }
TextField {
id: input
Layout.fillWidth: true
echoMode: TextInput.Normal
readOnly: root.readOnly
enabled: root.enabled
color: Color.mOnSurface
placeholderTextColor: Color.mOnSurface
background: null
font.pointSize: Style.fontSizeXS * scaling
onEditingFinished: root.editingFinished()
// Text changes are observable via the aliased 'text' property (root.text) and its 'textChanged' signal.
// No additional callback is invoked here to avoid conflicts with QML's onTextChanged handler semantics.
}
TextField {
id: input
Layout.fillWidth: true
echoMode: TextInput.Normal
readOnly: root.readOnly
enabled: root.enabled
color: Color.mOnSurface
placeholderTextColor: Color.mOnSurfaceVariant
background: null
font.pointSize: Style.fontSizeS * scaling
onEditingFinished: root.editingFinished()
}
}
}