This commit is contained in:
2026-03-25 18:19:37 +01:00
parent 24a14b41d7
commit 3114ecb690
30 changed files with 1787 additions and 12 deletions
+27
View File
@@ -0,0 +1,27 @@
pragma Singleton
import Quickshell
import QtQuick
Singleton {
id: root
property string highlightedSetting: ""
function clear() {
highlightedSetting = "";
}
function highlight(settingName: string) {
highlightedSetting = settingName;
highlightTimer.restart();
}
Timer {
id: highlightTimer
interval: 2000
onTriggered: root.clear()
}
}
+14 -1
View File
@@ -14,7 +14,20 @@ Item {
required property Item content required property Item content
implicitHeight: clayout.contentHeight + Appearance.padding.smaller * 2 signal settingSelected(string category, string section, string settingName)
// Function to select category by key
function selectCategory(categoryKey: string) {
for (let i = 0; i < listModel.count; i++) {
if (listModel.get(i).key === categoryKey) {
clayout.currentIndex = i;
root.content.currentCategory = categoryKey;
return;
}
}
}
implicitHeight: searchBar.implicitHeight + Appearance.spacing.smaller + clayout.contentHeight + Appearance.padding.smaller * 2
implicitWidth: clayout.contentWidth + Appearance.padding.smaller * 2 implicitWidth: clayout.contentWidth + Appearance.padding.smaller * 2
ListModel { ListModel {
@@ -5,6 +5,8 @@ SettingsPage {
id: root id: root
SettingsSection { SettingsSection {
sectionId: "Scale"
SettingsHeader { SettingsHeader {
name: "Scale" name: "Scale"
} }
@@ -58,6 +60,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Fonts"
SettingsHeader { SettingsHeader {
name: "Fonts" name: "Fonts"
} }
@@ -97,6 +101,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Animation"
SettingsHeader { SettingsHeader {
name: "Animation" name: "Animation"
} }
@@ -122,6 +128,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Transparency"
SettingsHeader { SettingsHeader {
name: "Transparency" name: "Transparency"
} }
@@ -5,6 +5,8 @@ SettingsPage {
id: root id: root
SettingsSection { SettingsSection {
sectionId: "Wallpaper"
SettingsHeader { SettingsHeader {
name: "Wallpaper" name: "Wallpaper"
} }
+8
View File
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Bar"
SettingsHeader { SettingsHeader {
name: "Bar" name: "Bar"
} }
@@ -45,6 +47,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Popouts"
SettingsHeader { SettingsHeader {
name: "Popouts" name: "Popouts"
} }
@@ -111,6 +115,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Entries"
SettingsHeader { SettingsHeader {
name: "Entries" name: "Entries"
} }
@@ -123,6 +129,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Dock"
SettingsHeader { SettingsHeader {
name: "Dock" name: "Dock"
} }
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Dashboard"
SettingsHeader { SettingsHeader {
name: "Dashboard" name: "Dashboard"
} }
@@ -47,6 +49,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Performance"
SettingsHeader { SettingsHeader {
name: "Performance" name: "Performance"
} }
@@ -104,6 +108,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Layout Sizes"
SettingsHeader { SettingsHeader {
name: "Layout Sizes" name: "Layout Sizes"
} }
+5
View File
@@ -16,6 +16,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "General"
SettingsHeader { SettingsHeader {
name: "General" name: "General"
} }
@@ -46,6 +48,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Color"
SettingsHeader { SettingsHeader {
name: "Color" name: "Color"
} }
@@ -175,6 +179,7 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Default Apps"
z: -1 z: -1
SettingsHeader { SettingsHeader {
+8
View File
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Launcher"
SettingsHeader { SettingsHeader {
name: "Launcher" name: "Launcher"
} }
@@ -44,6 +46,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Fuzzy Search"
SettingsHeader { SettingsHeader {
name: "Fuzzy Search" name: "Fuzzy Search"
} }
@@ -92,6 +96,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Sizes"
SettingsHeader { SettingsHeader {
name: "Sizes" name: "Sizes"
} }
@@ -135,6 +141,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Actions"
SettingsHeader { SettingsHeader {
name: "Actions" name: "Actions"
} }
@@ -6,6 +6,8 @@ SettingsPage {
id: root id: root
SettingsSection { SettingsSection {
sectionId: "Lockscreen"
SettingsHeader { SettingsHeader {
name: "Lockscreen" name: "Lockscreen"
} }
@@ -84,6 +86,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Idle"
Idle { Idle {
} }
} }
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Notifications"
SettingsHeader { SettingsHeader {
name: "Notifications" name: "Notifications"
} }
@@ -78,6 +80,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Sizes"
SettingsHeader { SettingsHeader {
name: "Sizes" name: "Sizes"
} }
+4
View File
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "On Screen Display"
SettingsHeader { SettingsHeader {
name: "On Screen Display" name: "On Screen Display"
} }
@@ -53,6 +55,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Sizes"
SettingsHeader { SettingsHeader {
name: "Sizes" name: "Sizes"
} }
+4
View File
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Services"
SettingsHeader { SettingsHeader {
name: "Services" name: "Services"
} }
@@ -51,6 +53,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Media"
SettingsHeader { SettingsHeader {
name: "Media" name: "Media"
} }
+2
View File
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Sidebar"
SettingsHeader { SettingsHeader {
name: "Sidebar" name: "Sidebar"
} }
@@ -3,6 +3,8 @@ import qs.Config
SettingsPage { SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Utilities"
SettingsHeader { SettingsHeader {
name: "Utilities" name: "Utilities"
} }
@@ -45,6 +47,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "Toasts"
SettingsHeader { SettingsHeader {
name: "Toasts" name: "Toasts"
} }
@@ -147,6 +151,8 @@ SettingsPage {
} }
SettingsSection { SettingsSection {
sectionId: "VPN"
SettingsHeader { SettingsHeader {
name: "VPN" name: "VPN"
} }
+44 -2
View File
@@ -14,12 +14,35 @@ Item {
property string currentCategory: "general" property string currentCategory: "general"
readonly property real nonAnimHeight: Math.floor(screen.height / 1.5) + viewWrapper.anchors.margins * 2 readonly property real nonAnimHeight: Math.floor(screen.height / 1.5) + viewWrapper.anchors.margins * 2
readonly property real nonAnimWidth: view.implicitWidth + Math.floor(screen.width / 2) + viewWrapper.anchors.margins * 2 readonly property real nonAnimWidth: view.implicitWidth + Math.floor(screen.width / 2) + viewWrapper.anchors.margins * 2
property string pendingSection: ""
property string pendingSetting: ""
required property ShellScreen screen required property ShellScreen screen
required property PersistentProperties visibilities required property PersistentProperties visibilities
function scrollToSetting(section: string, settingName: string) {
// Wait for the StackView transition to complete, then scroll
root.pendingSection = section;
root.pendingSetting = settingName;
scrollTimer.restart();
}
implicitHeight: nonAnimHeight implicitHeight: nonAnimHeight
implicitWidth: nonAnimWidth implicitWidth: nonAnimWidth
Timer {
id: scrollTimer
interval: 50
onTriggered: {
if (root.pendingSection && stack.currentItem) {
stack.currentItem.scrollToSectionAndHighlight(root.pendingSection, root.pendingSetting);
root.pendingSection = "";
root.pendingSetting = "";
}
}
}
Connections { Connections {
function onCurrentCategoryChanged() { function onCurrentCategoryChanged() {
stack.pop(); stack.pop();
@@ -59,12 +82,26 @@ Item {
anchors.margins: Appearance.padding.smaller anchors.margins: Appearance.padding.smaller
radius: Appearance.rounding.large - Appearance.padding.smaller radius: Appearance.rounding.large - Appearance.padding.smaller
SettingsSearch {
id: searchBar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
onSettingSelected: (category, section, settingName) => {
root.selectCategory(category);
root.settingSelected(category, section, settingName);
}
}
Item { Item {
id: view id: view
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: searchBar.bottom
anchors.topMargin: Appearance.spacing.smaller
implicitWidth: layout.implicitWidth implicitWidth: layout.implicitWidth
Categories { Categories {
@@ -72,6 +109,10 @@ Item {
anchors.fill: parent anchors.fill: parent
content: root content: root
onSettingSelected: (category, section, settingName) => {
root.scrollToSetting(section, settingName);
}
} }
} }
@@ -82,7 +123,8 @@ Item {
anchors.left: view.right anchors.left: view.right
anchors.leftMargin: Appearance.spacing.smaller anchors.leftMargin: Appearance.spacing.smaller
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: searchBar.bottom
anchors.topMargin: Appearance.spacing.smaller
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
@@ -4,10 +4,12 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
ColumnLayout { ColumnLayout {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property string setting required property string setting
@@ -45,6 +47,22 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Appearance.spacing.smaller spacing: Appearance.spacing.smaller
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: root.implicitHeight
Layout.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
CustomText { CustomText {
Layout.fillWidth: true Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger font.pointSize: Appearance.font.size.larger
@@ -4,10 +4,12 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
ColumnLayout { ColumnLayout {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property string setting required property string setting
@@ -41,6 +43,22 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Appearance.spacing.smaller spacing: Appearance.spacing.smaller
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: root.implicitHeight
Layout.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
CustomText { CustomText {
Layout.fillWidth: true Layout.fillWidth: true
font.pointSize: Appearance.font.size.larger font.pointSize: Appearance.font.size.larger
@@ -6,6 +6,7 @@ import QtQuick.Layouts
import QtQml.Models import QtQml.Models
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
@@ -19,6 +20,7 @@ Item {
property var draggedModelData: null property var draggedModelData: null
property string draggedUid: "" property string draggedUid: ""
property bool dropAnimating: false property bool dropAnimating: false
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
property var pendingCommitEntries: [] property var pendingCommitEntries: []
@@ -231,6 +233,21 @@ Item {
Component.onCompleted: root.rebuildVisualEntries() Component.onCompleted: root.rebuildVisualEntries()
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
z: -1
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
ParallelAnimation { ParallelAnimation {
id: settleAnim id: settleAnim
@@ -2,10 +2,12 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property list<string> settings required property list<string> settings
@@ -33,6 +35,20 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2 Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout { RowLayout {
id: row id: row
@@ -2,10 +2,12 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property string setting required property string setting
@@ -22,6 +24,20 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2 Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout { RowLayout {
id: row id: row
@@ -2,16 +2,32 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property string value required property string value
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2 Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout { RowLayout {
id: row id: row
+18 -2
View File
@@ -2,20 +2,36 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
property real max: Infinity
property real min: -Infinity
required property string name required property string name
required property var object required property var object
required property string setting required property string setting
property real max: Infinity
property real min: -Infinity
property real step: 1 property real step: 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2 Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout { RowLayout {
id: row id: row
@@ -2,10 +2,12 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property list<string> settings required property list<string> settings
@@ -33,6 +35,20 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2 Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout { RowLayout {
id: row id: row
@@ -2,18 +2,34 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
property string addLabel: qsTr("Add entry")
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property string setting required property string setting
property string addLabel: qsTr("Add entry")
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: layout.implicitHeight Layout.preferredHeight: layout.implicitHeight
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
ColumnLayout { ColumnLayout {
id: layout id: layout
@@ -2,10 +2,12 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers
Item { Item {
id: root id: root
readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
required property string name required property string name
required property var object required property var object
required property string setting required property string setting
@@ -13,6 +15,20 @@ Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2 Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
Rectangle {
anchors.fill: parent
anchors.margins: -Appearance.padding.smaller
color: DynamicColors.palette.m3primaryContainer
opacity: root.highlighted ? 0.5 : 0
radius: Appearance.rounding.small
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.normal
}
}
}
RowLayout { RowLayout {
id: row id: row
@@ -9,6 +9,24 @@ CustomFlickable {
default property alias contentData: clayout.data default property alias contentData: clayout.data
// Find and scroll to a section by its sectionId, then highlight a specific setting
function scrollToSectionAndHighlight(sectionId: string, settingName: string) {
// Find the section with matching sectionId
for (let i = 0; i < clayout.children.length; i++) {
const section = clayout.children[i];
if (section.sectionId === sectionId) {
// Scroll to the section with some padding
const targetY = section.y - Appearance.padding.normal;
contentY = Math.max(0, Math.min(targetY, contentHeight - height));
// Use the singleton to highlight the setting
SettingsHighlight.highlight(settingName);
return true;
}
}
return false;
}
contentHeight: clayout.implicitHeight contentHeight: clayout.implicitHeight
TapHandler { TapHandler {
@@ -8,6 +8,7 @@ CustomRect {
default property alias contentData: layout.data default property alias contentData: layout.data
property real contentPadding: Appearance.padding.large property real contentPadding: Appearance.padding.large
property string sectionId: ""
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: layout.implicitHeight + contentPadding * 2 Layout.preferredHeight: layout.implicitHeight + contentPadding * 2
File diff suppressed because it is too large Load Diff
+310
View File
@@ -0,0 +1,310 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import qs.Components
import qs.Config
import "../../scripts/fuzzysort.js" as Fuzzy
import "./SettingsIndex.mjs" as SettingsIndex
Item {
id: root
property alias text: searchField.text
signal settingSelected(string category, string section, string settingName)
function close() {
searchField.text = "";
searchField.focus = false;
popup.close();
}
function search(query) {
resultsModel.clear();
if (!query || query.trim() === "") {
popup.close();
return;
}
const results = SettingsIndex.searchSettings(query, Fuzzy);
for (const result of results.slice(0, 10)) {
resultsModel.append({
name: result.name,
category: result.category,
categoryName: result.categoryName,
section: result.section,
matchType: result.matchType
});
}
if (resultsModel.count > 0) {
popup.open();
} else {
popup.close();
}
}
implicitHeight: searchContainer.implicitHeight
implicitWidth: 200
ListModel {
id: resultsModel
}
CustomRect {
id: searchContainer
anchors.fill: parent
color: DynamicColors.tPalette.m3surfaceContainerHigh
implicitHeight: searchRow.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.full
RowLayout {
id: searchRow
anchors.fill: parent
anchors.leftMargin: Appearance.padding.normal
anchors.rightMargin: Appearance.padding.small
spacing: Appearance.spacing.small
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.larger
text: "search"
}
CustomTextField {
id: searchField
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
font.pointSize: Appearance.font.size.small
placeholderText: qsTr("Search settings...")
Keys.onDownPressed: {
if (popup.visible && resultsList.count > 0) {
resultsList.currentIndex = Math.min(resultsList.currentIndex + 1, resultsList.count - 1);
}
}
Keys.onEscapePressed: {
root.close();
}
Keys.onReturnPressed: {
if (popup.visible && resultsList.currentIndex >= 0) {
const item = resultsModel.get(resultsList.currentIndex);
root.settingSelected(item.category, item.section, item.name);
root.close();
}
}
Keys.onUpPressed: {
if (popup.visible && resultsList.count > 0) {
resultsList.currentIndex = Math.max(resultsList.currentIndex - 1, 0);
}
}
onTextChanged: {
searchTimer.restart();
}
}
// Clear button
IconButton {
Layout.alignment: Qt.AlignVCenter
font.pointSize: Appearance.font.size.larger
icon: "close"
opacity: searchField.text.length > 0 ? 1 : 0
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
onClicked: {
root.close();
}
}
}
}
// Debounce timer for search
Timer {
id: searchTimer
interval: 150
onTriggered: root.search(searchField.text)
}
// Results dropdown
Popup {
id: popup
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
implicitHeight: Math.min(resultsList.contentHeight + Appearance.padding.small * 2 + 10, (contentItem.view.delegate.implicitHeight + Appearance.spacing.smaller) * 5 - Appearance.spacing.smaller + 10)
implicitWidth: root.width + Appearance.padding.small * 2
modal: false
padding: 0
x: root.width / 2 - popup.width / 2
y: searchContainer.height + Appearance.spacing.small
background: Item {
}
contentItem: Item {
property alias view: resultsList
Elevation {
id: popupShadow
anchors.centerIn: parent
height: popup.implicitHeight - 10
level: 2
radius: Appearance.rounding.normal
width: popup.implicitWidth - 10
CustomRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer
radius: Appearance.rounding.normal
CustomListView {
id: resultsList
anchors.fill: parent
anchors.margins: Appearance.padding.small
clip: true
currentIndex: 0
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
model: resultsModel
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Appearance.spacing.smaller
delegate: SearchResultItem {
required property string category
required property string categoryName
required property int index
required property string matchType
required property string name
required property string section
highlighted: index === resultsList.currentIndex
width: resultsList.width
onClicked: {
root.settingSelected(category, section, name);
root.close();
}
}
highlight: CustomRect {
color: DynamicColors.palette.m3primary
implicitHeight: resultsList.currentItem?.implicitHeight ?? 0
implicitWidth: resultsList.width
radius: Appearance.rounding.normal - Appearance.padding.smaller
y: resultsList.currentItem?.y ?? 0
Behavior on y {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
}
}
}
}
}
enter: Transition {
Anim {
duration: Appearance.anim.durations.small
from: 0
property: "opacity"
to: 1
}
Anim {
duration: Appearance.anim.durations.small
from: 0.95
property: "scale"
to: 1.0
}
}
exit: Transition {
Anim {
duration: Appearance.anim.durations.smaller
from: 1
property: "opacity"
to: 0
}
}
}
// Search result item component
component SearchResultItem: CustomRect {
id: resultItem
property bool highlighted: false
signal clicked
implicitHeight: resultLayout.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.small
ColumnLayout {
id: resultLayout
anchors.fill: parent
anchors.margins: Appearance.padding.small
spacing: 2
// Setting name
CustomText {
Layout.fillWidth: true
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
elide: Text.ElideRight
font.pointSize: Appearance.font.size.small
font.weight: Font.Medium
text: resultItem.name
}
// Category and section path
RowLayout {
Layout.fillWidth: true
spacing: Appearance.spacing.smaller
CustomText {
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.smaller
opacity: 0.8
text: resultItem.categoryName
}
CustomText {
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.smaller
opacity: 0.6
text: ""
}
CustomText {
Layout.fillWidth: true
color: highlighted ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurfaceVariant
elide: Text.ElideRight
font.pointSize: Appearance.font.size.smaller
opacity: 0.8
text: resultItem.section
}
}
}
StateLayer {
onClicked: resultItem.clicked()
}
}
}
+4 -2
View File
@@ -122,9 +122,11 @@ stdenv.mkDerivation {
substituteInPlace shell.qml \ substituteInPlace shell.qml \
--replace-fail 'ShellRoot {' 'ShellRoot { settings.watchFiles: false' --replace-fail 'ShellRoot {' 'ShellRoot { settings.watchFiles: false'
substituteInPlace Helpers/Hyprsunset.qml \ substituteInPlace Helpers/Hyprsunset.qml \
--replace-fail 'Quickshell.execDetached(["hyprctl", "hyprsunset", "temperature", `${temp}`]);' 'Quickshell.execDetached(["hyprsunset", "-t", `${temp}`]);' --replace-fail 'Quickshell.execDetached(["hyprctl", "hyprsunset", "temperature", `''${temp}`]);' \
'Quickshell.execDetached(["hyprsunset", "-t", `''${temp}`]);'
substituteInPlace Helpers/Hyprsunset.qml \ substituteInPlace Helpers/Hyprsunset.qml \
--replace-fail 'Quickshell.execDetached(["hyprctl", "hyprsunset", "identity"]);' 'Quickshell.execDetached(["hyprsunset", "--identity"]);' --replace-fail 'Quickshell.execDetached(["hyprctl", "hyprsunset", "identity"]);' \
'Quickshell.execDetached(["hyprsunset", "--identity"]);'
''; '';
postInstall = '' postInstall = ''