1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-28 23:42:51 -05:00

better fuzzy search, sweeping clean and qmlfmt of Widgets

This commit is contained in:
bbedward
2025-09-03 12:52:03 -04:00
parent 886c6877d5
commit d4db8a01fe
50 changed files with 2112 additions and 2010 deletions

View File

@@ -1,4 +1,4 @@
import "../Common/fuzzysort.js" as FuzzySort
import "../Common/fzf.js" as Fzf
import QtQuick
import QtQuick.Controls
import qs.Common
@@ -11,10 +11,10 @@ Rectangle {
property string description: ""
property string currentValue: ""
property var options: []
property var optionIcons: [] // Array of icon names corresponding to options
property var optionIcons: []
property bool forceRecreate: false
property bool enableFuzzySearch: false
property int popupWidthOffset: 0 // How much wider the popup should be than the button
property int popupWidthOffset: 0
property int maxPopupHeight: 400
signal valueChanged(string value)
@@ -23,20 +23,20 @@ Rectangle {
height: 60
radius: Theme.cornerRadius
color: "transparent"
Component.onCompleted: {
forceRecreateTimer.start()
}
Component.onCompleted: forceRecreateTimer.start()
Component.onDestruction: {
var popup = popupLoader.item
if (popup && popup.visible)
const popup = popupLoader.item
if (popup && popup.visible) {
popup.close()
}
}
onVisibleChanged: {
var popup = popupLoader.item
if (!visible && popup && popup.visible)
const popup = popupLoader.item
if (!visible && popup && popup.visible) {
popup.close()
else if (visible)
} else if (visible) {
forceRecreateTimer.start()
}
}
Timer {
@@ -44,12 +44,9 @@ Rectangle {
interval: 50
repeat: false
onTriggered: {
root.forceRecreate = !root.forceRecreate
}
onTriggered: root.forceRecreate = !root.forceRecreate
}
Column {
anchors.left: parent.left
anchors.right: dropdown.left
@@ -95,16 +92,20 @@ Rectangle {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
var popup = popupLoader.item
if (popup && popup.visible) {
popup.close()
} else if (popup) {
var pos = dropdown.mapToItem(Overlay.overlay, 0,
dropdown.height + 4)
popup.x = pos.x - (root.popupWidthOffset / 2)
popup.y = pos.y
popup.open()
const popup = popupLoader.item
if (!popup) {
return
}
if (popup.visible) {
popup.close()
return
}
const pos = dropdown.mapToItem(Overlay.overlay, 0, dropdown.height + 4)
popup.x = pos.x - (root.popupWidthOffset / 2)
popup.y = pos.y
popup.open()
}
}
@@ -118,9 +119,8 @@ Rectangle {
DankIcon {
name: {
var currentIndex = root.options.indexOf(root.currentValue)
return root.optionIcons.length > currentIndex
&& currentIndex >= 0 ? root.optionIcons[currentIndex] : ""
const currentIndex = root.options.indexOf(root.currentValue)
return currentIndex >= 0 && root.optionIcons.length > currentIndex ? root.optionIcons[currentIndex] : ""
}
size: 18
color: Theme.surfaceVariantText
@@ -131,9 +131,7 @@ Rectangle {
text: root.currentValue
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
width: root.width <= 60 ?
(dropdown.width - expandIcon.width - Theme.spacingS * 2) :
(dropdown.width - contentRow.x - expandIcon.width - Theme.spacingM - Theme.spacingS)
width: root.width <= 60 ? dropdown.width - expandIcon.width - Theme.spacingS * 2 : dropdown.width - contentRow.x - expandIcon.width - Theme.spacingM - Theme.spacingS
elide: root.width <= 60 ? Text.ElideNone : Text.ElideRight
horizontalAlignment: root.width <= 60 ? Text.AlignHCenter : Text.AlignLeft
}
@@ -169,61 +167,61 @@ Rectangle {
property string searchQuery: ""
property var filteredOptions: []
property int selectedIndex: -1
property var fzfFinder: new Fzf.Finder(root.options, {
"selector": option => option,
"limit": 50,
"casing": "case-insensitive"
})
function updateFilteredOptions() {
if (!root.enableFuzzySearch || searchQuery.length === 0) {
filteredOptions = root.options
} else {
var results = FuzzySort.go(searchQuery, root.options, {
"limit": 50,
"threshold": -10000
})
filteredOptions = results.map(function (result) {
return result.target
})
selectedIndex = -1
return
}
const results = fzfFinder.find(searchQuery)
filteredOptions = results.map(result => result.item)
selectedIndex = -1
}
function selectNext() {
if (filteredOptions.length > 0) {
selectedIndex = (selectedIndex + 1) % filteredOptions.length
listView.positionViewAtIndex(selectedIndex,
ListView.Contain)
if (filteredOptions.length === 0) {
return
}
selectedIndex = (selectedIndex + 1) % filteredOptions.length
listView.positionViewAtIndex(selectedIndex, ListView.Contain)
}
function selectPrevious() {
if (filteredOptions.length > 0) {
selectedIndex = selectedIndex
<= 0 ? filteredOptions.length - 1 : selectedIndex - 1
listView.positionViewAtIndex(selectedIndex,
ListView.Contain)
if (filteredOptions.length === 0) {
return
}
selectedIndex = selectedIndex <= 0 ? filteredOptions.length - 1 : selectedIndex - 1
listView.positionViewAtIndex(selectedIndex, ListView.Contain)
}
function selectCurrent() {
if (selectedIndex >= 0
&& selectedIndex < filteredOptions.length) {
root.currentValue = filteredOptions[selectedIndex]
root.valueChanged(filteredOptions[selectedIndex])
close()
if (selectedIndex < 0 || selectedIndex >= filteredOptions.length) {
return
}
root.currentValue = filteredOptions[selectedIndex]
root.valueChanged(filteredOptions[selectedIndex])
close()
}
parent: Overlay.overlay
width: dropdown.width + root.popupWidthOffset
height: Math.min(root.maxPopupHeight,
(root.enableFuzzySearch ? 54 : 0) + Math.min(
filteredOptions.length, 10) * 36 + 16)
height: Math.min(root.maxPopupHeight, (root.enableFuzzySearch ? 54 : 0) + Math.min(filteredOptions.length, 10) * 36 + 16)
padding: 0
modal: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
onOpened: {
searchQuery = ""
updateFilteredOptions()
if (root.enableFuzzySearch && searchField.visible)
if (root.enableFuzzySearch && searchField.visible) {
searchField.forceActiveFocus()
}
}
background: Rectangle {
@@ -231,9 +229,7 @@ Rectangle {
}
contentItem: Rectangle {
color: Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 1)
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
border.color: Theme.primarySelected
border.width: 1
radius: Theme.cornerRadius
@@ -288,28 +284,18 @@ Rectangle {
model: filteredOptions
spacing: 2
// Qt 6.9+ scrolling: flickDeceleration/maximumFlickVelocity only affect touch now
interactive: true
flickDeceleration: 1500 // Touch only in Qt 6.9+ // Lower = more momentum, longer scrolling
maximumFlickVelocity: 2000 // Touch only in Qt 6.9+ // Higher = faster maximum scroll speed
flickDeceleration: 1500
maximumFlickVelocity: 2000
boundsBehavior: Flickable.DragAndOvershootBounds
boundsMovement: Flickable.FollowBoundsBehavior
pressDelay: 0
flickableDirection: Flickable.VerticalFlick
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
}
ScrollBar.horizontal: ScrollBar {
policy: ScrollBar.AlwaysOff
}
delegate: Rectangle {
property bool isSelected: selectedIndex === index
property bool isCurrentValue: root.currentValue === modelData
property int optionIndex: root.options.indexOf(
modelData)
property int optionIndex: root.options.indexOf(modelData)
width: ListView.view.width
height: 32
@@ -323,9 +309,7 @@ Rectangle {
spacing: Theme.spacingS
DankIcon {
name: optionIndex >= 0
&& root.optionIcons.length
> optionIndex ? root.optionIcons[optionIndex] : ""
name: optionIndex >= 0 && root.optionIcons.length > optionIndex ? root.optionIcons[optionIndex] : ""
size: 18
color: isCurrentValue ? Theme.primary : Theme.surfaceVariantText
visible: name !== ""