mirror of
https://github.com/linuxdeepin/deepin-music.git
synced 2026-10-16 21:20:47 +08:00
fix: add keyboard navigation for search dropdown
1. Root cause: SearchResultDialog.qml had no keyboard navigation; SearchEdit only handled Return key, arrow keys were consumed by TextField default cursor movement 2. Fix: add selectedIndex tracking, moveSelection/activateSelection methods and highlight in SearchResultDialog; add Keys.onDownPressed /onUpPressed and extend onReturnPressed in WindowTitlebar SearchEdit 3. Impact: users can now navigate search results with arrow keys and confirm with Enter; mouse interaction unchanged Log: Search results now support keyboard navigation with arrow keys Influence: 1. Test arrow key navigation in search result dropdown 2. Test Enter key to activate selected search result 3. Verify mouse hover and click still work as before fix: 搜索结果下拉列表添加键盘导航 1. 根因:SearchResultDialog.qml 无键盘导航机制,SearchEdit 仅处理 回车键,方向键被 TextField 默认光标移动行为消费 2. 方案:在 SearchResultDialog 添加 selectedIndex 追踪、 moveSelection/activateSelection 方法和高亮显示;在 WindowTitlebar 的 SearchEdit 添加方向键处理并扩展回车键逻辑 3. 影响:用户可通过方向键导航搜索结果并回车确认,鼠标交互不受影响 Log: 搜索结果支持方向键导航和回车选择 Influence: 1. 测试搜索结果下拉列表中方向键导航 2. 测试回车键激活选中的搜索结果 3. 验证鼠标悬停和点击功能无回归 PMS: BUG-375953
This commit is contained in:
@@ -12,11 +12,48 @@ Popup {
|
||||
property string pattern: ""
|
||||
|
||||
property int itemHeight: 40
|
||||
property int selectedIndex: -1
|
||||
property int resultCount: (songList == null ? 0 : songList.length) + artistModel.count + albumModel.count
|
||||
|
||||
signal searchItemTriggered(string value, int type)
|
||||
|
||||
id: searchResultRect
|
||||
width: 360
|
||||
|
||||
// Moves the keyboard selection by offset, wrapping around available results.
|
||||
function moveSelection(offset) {
|
||||
if (resultCount <= 0)
|
||||
return
|
||||
|
||||
if (selectedIndex < 0) {
|
||||
selectedIndex = offset > 0 ? 0 : resultCount - 1
|
||||
return
|
||||
}
|
||||
|
||||
selectedIndex = (selectedIndex + offset + resultCount) % resultCount
|
||||
}
|
||||
|
||||
// Activates the currently selected result and returns whether activation succeeded.
|
||||
function activateSelection() {
|
||||
if (selectedIndex < 0 || selectedIndex >= resultCount)
|
||||
return false
|
||||
|
||||
var songCount = songList == null ? 0 : songList.length
|
||||
if (selectedIndex < songCount) {
|
||||
searchItemTriggered(songList[selectedIndex], 0)
|
||||
return true
|
||||
}
|
||||
|
||||
var artistIndex = selectedIndex - songCount
|
||||
if (artistIndex < artistModel.count) {
|
||||
searchItemTriggered(artistModel.get(artistIndex).name, 1)
|
||||
return true
|
||||
}
|
||||
|
||||
searchItemTriggered(albumModel.get(artistIndex - artistModel.count).name, 2)
|
||||
return true
|
||||
}
|
||||
|
||||
height: (songList == null ? 0 : songList.length + artistModel.count + albumModel.count) * itemHeight + 110
|
||||
leftPadding: 8
|
||||
rightPadding: 8
|
||||
@@ -66,10 +103,17 @@ Popup {
|
||||
id: resultItemTextDelegate
|
||||
Rectangle {
|
||||
id: itemRect
|
||||
property int resultIndex: index
|
||||
width: parent.width
|
||||
height: itemHeight
|
||||
radius: 6
|
||||
color: "#00000000"
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: parent.radius
|
||||
color: palette.highlight
|
||||
visible: searchResultRect.selectedIndex === itemRect.resultIndex
|
||||
}
|
||||
Row {
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -104,10 +148,20 @@ Popup {
|
||||
id: resultItemImgDelegate
|
||||
Rectangle {
|
||||
id: itemRect
|
||||
property int resultIndex: (model.type === "album"
|
||||
? (searchResultRect.songList == null ? 0 : searchResultRect.songList.length)
|
||||
+ searchResultRect.artistModel.count
|
||||
: (searchResultRect.songList == null ? 0 : searchResultRect.songList.length)) + index
|
||||
width: parent.width
|
||||
height: itemHeight
|
||||
radius: 6
|
||||
color: "#00000000"
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: parent.radius
|
||||
color: palette.highlight
|
||||
visible: searchResultRect.selectedIndex === itemRect.resultIndex
|
||||
}
|
||||
Row {
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
@@ -272,12 +272,29 @@ TitleBar {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
placeholder: qsTr("Search")
|
||||
enabled: Presenter.isExistMeta()
|
||||
Keys.onDownPressed: function(event) {
|
||||
var searchResDlg = searchResultLoader.item
|
||||
if (!searchResDlg || !searchResDlg.visible)
|
||||
return
|
||||
searchResDlg.moveSelection(1)
|
||||
event.accepted = true
|
||||
}
|
||||
Keys.onUpPressed: function(event) {
|
||||
var searchResDlg = searchResultLoader.item
|
||||
if (!searchResDlg || !searchResDlg.visible)
|
||||
return
|
||||
searchResDlg.moveSelection(-1)
|
||||
event.accepted = true
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
//console.log("SearchEdit: Keys.onEnterPressed....")
|
||||
var searchResDlg = searchResultLoader.item
|
||||
if (text.length <= 0 || !searchResDlg || searchResDlg.songList == null)
|
||||
return
|
||||
|
||||
if (searchResDlg.visible && searchResDlg.activateSelection())
|
||||
return
|
||||
|
||||
var type = -1
|
||||
if (searchResDlg.songList.length > 0)
|
||||
type = 0
|
||||
@@ -372,6 +389,7 @@ TitleBar {
|
||||
}
|
||||
|
||||
var searchResDlg = searchResultLoader.item
|
||||
searchResDlg.selectedIndex = -1
|
||||
searchResDlg.songList = []
|
||||
searchResDlg.artistModel.clear()
|
||||
searchResDlg.albumModel.clear()
|
||||
|
||||
Reference in New Issue
Block a user