SettingsPanel: converted to layout

This commit is contained in:
LemmyCook 2025-09-05 18:05:42 -04:00
parent cbffc1a14c
commit 9a14a5cc10

View file

@ -267,239 +267,269 @@ NPanel {
} }
panelContent: Rectangle { panelContent: Rectangle {
anchors.fill: parent
anchors.margins: Style.marginL * scaling
color: Color.transparent color: Color.transparent
// Scrolling via keyboard // Main layout container that fills the panel
Shortcut { ColumnLayout {
sequence: "Down"
onActivated: root.scrollDown()
enabled: root.opened
}
Shortcut {
sequence: "Up"
onActivated: root.scrollUp()
enabled: root.opened
}
Shortcut {
sequence: "Ctrl+J"
onActivated: root.scrollDown()
enabled: root.opened
}
Shortcut {
sequence: "Ctrl+K"
onActivated: root.scrollUp()
enabled: root.opened
}
Shortcut {
sequence: "PgDown"
onActivated: root.scrollPageDown()
enabled: root.opened
}
Shortcut {
sequence: "PgUp"
onActivated: root.scrollPageUp()
enabled: root.opened
}
// Changing tab via keyboard
Shortcut {
sequence: "Tab"
onActivated: root.selectNextTab()
enabled: root.opened
}
Shortcut {
sequence: "Shift+Tab"
onActivated: root.selectPreviousTab()
enabled: root.opened
}
RowLayout {
anchors.fill: parent anchors.fill: parent
spacing: Style.marginM * scaling anchors.margins: Style.marginL * scaling
spacing: 0
Rectangle { // Keyboard shortcuts container
id: sidebar Item {
Layout.preferredWidth: 220 * scaling Layout.preferredWidth: 0
Layout.fillHeight: true Layout.preferredHeight: 0
color: Color.mSurfaceVariant
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
radius: Style.radiusM * scaling
MouseArea { // Scrolling via keyboard
anchors.fill: parent Shortcut {
acceptedButtons: Qt.NoButton // Don't interfere with clicks sequence: "Down"
property int wheelAccumulator: 0 onActivated: root.scrollDown()
onWheel: wheel => { enabled: root.opened
wheelAccumulator += wheel.angleDelta.y
if (wheelAccumulator >= 120) {
root.selectPreviousTab()
wheelAccumulator = 0
} else if (wheelAccumulator <= -120) {
root.selectNextTab()
wheelAccumulator = 0
}
wheel.accepted = true
}
} }
Column { Shortcut {
anchors.fill: parent sequence: "Up"
anchors.margins: Style.marginS * scaling onActivated: root.scrollUp()
spacing: Style.marginXS * 1.5 * scaling enabled: root.opened
}
Repeater { Shortcut {
id: sections sequence: "Ctrl+J"
model: root.tabsModel onActivated: root.scrollDown()
delegate: Rectangle { enabled: root.opened
id: tabItem }
width: parent.width
height: 32 * scaling
radius: Style.radiusS * scaling
color: selected ? Color.mPrimary : (tabItem.hovering ? Color.mTertiary : Color.transparent)
readonly property bool selected: index === currentTabIndex
property bool hovering: false
property color tabTextColor: selected ? Color.mOnPrimary : (tabItem.hovering ? Color.mOnTertiary : Color.mOnSurface)
Behavior on color { Shortcut {
ColorAnimation { sequence: "Ctrl+K"
duration: Style.animationFast onActivated: root.scrollUp()
} enabled: root.opened
} }
Behavior on tabTextColor { Shortcut {
ColorAnimation { sequence: "PgDown"
duration: Style.animationFast onActivated: root.scrollPageDown()
} enabled: root.opened
} }
RowLayout { Shortcut {
anchors.fill: parent sequence: "PgUp"
anchors.leftMargin: Style.marginS * scaling onActivated: root.scrollPageUp()
anchors.rightMargin: Style.marginS * scaling enabled: root.opened
spacing: Style.marginS * scaling }
// Tab icon on the left side
NIcon { // Changing tab via keyboard
text: modelData.icon Shortcut {
color: tabTextColor sequence: "Tab"
font.pointSize: Style.fontSizeL * scaling onActivated: root.selectNextTab()
} enabled: root.opened
// Tab label on the left side }
NText {
text: modelData.label Shortcut {
color: tabTextColor sequence: "Shift+Tab"
font.pointSize: Style.fontSizeM * scaling onActivated: root.selectPreviousTab()
font.weight: Style.fontWeightBold enabled: root.opened
Layout.fillWidth: true
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onEntered: tabItem.hovering = true
onExited: tabItem.hovering = false
onCanceled: tabItem.hovering = false
onClicked: currentTabIndex = index
}
}
}
} }
} }
// Content // Main content area
Rectangle { RowLayout {
id: contentPane
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
radius: Style.radiusM * scaling spacing: Style.marginM * scaling
color: Color.mSurfaceVariant
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
clip: true
ColumnLayout { // Sidebar
id: contentLayout Rectangle {
anchors.fill: parent id: sidebar
anchors.margins: Style.marginL * scaling Layout.preferredWidth: 220 * scaling
spacing: Style.marginS * scaling Layout.fillHeight: true
Layout.alignment: Qt.AlignTop
color: Color.mSurfaceVariant
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
radius: Style.radiusM * scaling
RowLayout { MouseArea {
id: headerRow anchors.fill: parent
Layout.fillWidth: true acceptedButtons: Qt.NoButton // Don't interfere with clicks
spacing: Style.marginS * scaling property int wheelAccumulator: 0
onWheel: wheel => {
// Tab label on the main right side wheelAccumulator += wheel.angleDelta.y
NText { if (wheelAccumulator >= 120) {
text: root.tabsModel[currentTabIndex].label root.selectPreviousTab()
font.pointSize: Style.fontSizeXL * scaling wheelAccumulator = 0
font.weight: Style.fontWeightBold } else if (wheelAccumulator <= -120) {
color: Color.mPrimary root.selectNextTab()
Layout.fillWidth: true wheelAccumulator = 0
} }
NIconButton { wheel.accepted = true
icon: "close" }
tooltipText: "Close"
Layout.alignment: Qt.AlignVCenter
onClicked: root.close()
}
} }
NDivider { ColumnLayout {
Layout.fillWidth: true anchors.fill: parent
} anchors.margins: Style.marginS * scaling
spacing: Style.marginXS * 1.5 * scaling
Item {
Layout.fillWidth: true
Layout.fillHeight: true
Repeater { Repeater {
id: sections
model: root.tabsModel model: root.tabsModel
delegate: Loader { delegate: Rectangle {
anchors.fill: parent id: tabItem
active: index === root.currentTabIndex Layout.fillWidth: true
Layout.preferredHeight: tabEntryRow.implicitHeight + Style.marginS * scaling * 2
radius: Style.radiusS * scaling
color: selected ? Color.mPrimary : (tabItem.hovering ? Color.mTertiary : Color.transparent)
readonly property bool selected: index === currentTabIndex
property bool hovering: false
property color tabTextColor: selected ? Color.mOnPrimary : (tabItem.hovering ? Color.mOnTertiary : Color.mOnSurface)
onStatusChanged: { Behavior on color {
if (status === Loader.Ready && item) { ColorAnimation {
// Find and store reference to the ScrollView duration: Style.animationFast
const scrollView = item.children[0]
if (scrollView && scrollView.toString().includes("ScrollView")) {
root.activeScrollView = scrollView
}
} }
} }
sourceComponent: Flickable { Behavior on tabTextColor {
// Using a Flickable here with a pressDelay to fix conflict between ColorAnimation {
// ScrollView and NTextInput. This fix the weird text selection issue. duration: Style.animationFast
id: flickable }
}
RowLayout {
id: tabEntryRow
anchors.fill: parent anchors.fill: parent
pressDelay: 200 anchors.margins: Style.marginS * scaling
spacing: Style.marginS * scaling
ScrollView { // Tab icon
id: scrollView NIcon {
anchors.fill: parent text: modelData.icon
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff color: tabTextColor
ScrollBar.vertical.policy: ScrollBar.AsNeeded font.pointSize: Style.fontSizeL * scaling
padding: Style.marginL * scaling }
clip: true
Component.onCompleted: { // Tab label
root.activeScrollView = scrollView NText {
text: modelData.label
color: tabTextColor
font.pointSize: Style.fontSizeM * scaling
font.weight: Style.fontWeightBold
Layout.fillWidth: true
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.LeftButton
onEntered: tabItem.hovering = true
onExited: tabItem.hovering = false
onCanceled: tabItem.hovering = false
onClicked: currentTabIndex = index
}
}
}
Item {
Layout.fillHeight: true
}
}
}
// Content pane
Rectangle {
id: contentPane
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignTop
radius: Style.radiusM * scaling
color: Color.mSurfaceVariant
border.color: Color.mOutline
border.width: Math.max(1, Style.borderS * scaling)
clip: true
ColumnLayout {
id: contentLayout
anchors.fill: parent
anchors.margins: Style.marginL * scaling
spacing: Style.marginS * scaling
// Header row
RowLayout {
id: headerRow
Layout.fillWidth: true
spacing: Style.marginS * scaling
// Tab title
NText {
text: root.tabsModel[currentTabIndex]?.label || ""
font.pointSize: Style.fontSizeXL * scaling
font.weight: Style.fontWeightBold
color: Color.mPrimary
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
// Close button
NIconButton {
icon: "close"
tooltipText: "Close"
Layout.alignment: Qt.AlignVCenter
onClicked: root.close()
}
}
// Divider
NDivider {
Layout.fillWidth: true
}
// Tab content area
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: Color.transparent
Repeater {
model: root.tabsModel
delegate: Loader {
anchors.fill: parent
active: index === root.currentTabIndex
onStatusChanged: {
if (status === Loader.Ready && item) {
// Find and store reference to the ScrollView
const scrollView = item.children[0]
if (scrollView && scrollView.toString().includes("ScrollView")) {
root.activeScrollView = scrollView
}
} }
}
Loader { sourceComponent: Flickable {
active: true // Using a Flickable here with a pressDelay to fix conflict between
sourceComponent: root.tabsModel[index].source // ScrollView and NTextInput. This fixes the weird text selection issue.
width: scrollView.availableWidth id: flickable
anchors.fill: parent
pressDelay: 200
ScrollView {
id: scrollView
anchors.fill: parent
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
padding: Style.marginL * scaling
clip: true
Component.onCompleted: {
root.activeScrollView = scrollView
}
Loader {
active: true
sourceComponent: root.tabsModel[index]?.source
width: scrollView.availableWidth
}
} }
} }
} }