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.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded ScrollBar.vertical.policy: ScrollBar.AsNeeded
padding: Style.marginL * scaling padding: Style.marginL * scaling
clip: true
Loader { Loader {
active: true active: true

View file

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

View file

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

View file

@ -25,10 +25,9 @@ ColumnLayout {
NTextInput { NTextInput {
label: "Profile Picture" 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 text: Settings.data.general.avatarImage
placeholderText: "/home/user/.face" placeholderText: "/home/user/.face"
Layout.fillWidth: true
onEditingFinished: { onEditingFinished: {
Settings.data.general.avatarImage = text Settings.data.general.avatarImage = text
} }

View file

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

View file

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

View file

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

View file

@ -4,13 +4,14 @@ import QtQuick.Layouts
import qs.Commons import qs.Commons
import qs.Services import qs.Services
Item { ColumnLayout {
id: root id: root
property string label: "" property string label: ""
property string description: "" property string description: ""
property bool readOnly: false property bool readOnly: false
property bool enabled: true property bool enabled: true
property int inputMaxWidth: 420 * scaling
property alias text: input.text property alias text: input.text
property alias placeholderText: input.placeholderText property alias placeholderText: input.placeholderText
@ -18,61 +19,53 @@ Item {
signal editingFinished signal editingFinished
// Sizing spacing: Style.marginS * scaling
implicitWidth: Style.sliderWidth * 1.6 * scaling implicitHeight: frame.height
implicitHeight: Style.baseWidgetSize * 2.75 * scaling
ColumnLayout { NLabel {
spacing: Style.marginXXS * scaling label: root.label
Layout.fillWidth: true description: root.description
visible: root.label !== "" || root.description !== ""
}
NLabel { // Container
label: root.label Rectangle {
description: root.description 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 RowLayout {
Rectangle { anchors.fill: parent
id: frame anchors.leftMargin: Style.marginM * scaling
Layout.topMargin: Style.marginXS * scaling anchors.rightMargin: Style.marginM * scaling
implicitWidth: root.width spacing: Style.marginS * scaling
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)
// Focus ring TextField {
Rectangle { id: input
anchors.fill: parent Layout.fillWidth: true
radius: frame.radius echoMode: TextInput.Normal
color: Color.transparent readOnly: root.readOnly
border.color: input.activeFocus ? Color.mSecondary : Color.transparent enabled: root.enabled
border.width: input.activeFocus ? Math.max(1, Style.borderS * scaling) : 0 color: Color.mOnSurface
} placeholderTextColor: Color.mOnSurfaceVariant
background: null
RowLayout { font.pointSize: Style.fontSizeS * scaling
anchors.fill: parent onEditingFinished: root.editingFinished()
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.
}
} }
} }
} }