167 lines
4.9 KiB
QML
167 lines
4.9 KiB
QML
|
import QtQuick 2.14
|
||
|
import QtQuick.Controls 2.14
|
||
|
import QtQuick.Layouts 1.14
|
||
|
import QtGraphicalEffects 1.0
|
||
|
|
||
|
import StatusQ.Components 0.1
|
||
|
import StatusQ.Controls 0.1
|
||
|
import StatusQ.Core 0.1
|
||
|
import StatusQ.Core.Theme 0.1
|
||
|
|
||
|
import utils 1.0
|
||
|
|
||
|
Popup {
|
||
|
id: root
|
||
|
|
||
|
width: 400
|
||
|
height: 300
|
||
|
|
||
|
property alias model: listView.model
|
||
|
|
||
|
// delegate interface has to be fulfilled
|
||
|
property Component delegate: Item {
|
||
|
property var modelData
|
||
|
property bool isCurrentItem
|
||
|
function filterAccepts(searchText) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
property string searchBoxPlaceholder: qsTr("Search...")
|
||
|
|
||
|
signal selected(int index, var modelData)
|
||
|
|
||
|
background: Rectangle {
|
||
|
radius: Style.current.radius
|
||
|
color: Style.current.background
|
||
|
border.color: Style.current.border
|
||
|
layer.enabled: true
|
||
|
layer.effect: DropShadow {
|
||
|
verticalOffset: 3
|
||
|
radius: 8
|
||
|
samples: 15
|
||
|
fast: true
|
||
|
cached: true
|
||
|
color: "#22000000"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ColumnLayout {
|
||
|
anchors.fill: parent
|
||
|
|
||
|
StatusInput {
|
||
|
id: searchBox
|
||
|
|
||
|
Layout.fillWidth: true
|
||
|
leftPadding: 0
|
||
|
rightPadding: 0
|
||
|
input.placeholderText: root.searchBoxPlaceholder
|
||
|
input.icon: StatusIconSettings {
|
||
|
width: 24
|
||
|
height: 24
|
||
|
name: "search"
|
||
|
color: Theme.palette.baseColor1
|
||
|
}
|
||
|
|
||
|
function goToNextAvailableIndex(up) {
|
||
|
var currentIndex = listView.currentIndex
|
||
|
for (var i = 0; i < listView.count; i++) {
|
||
|
currentIndex = up ? (currentIndex === 0 ? listView.count - 1 : currentIndex - 1)
|
||
|
: (currentIndex === listView.count - 1 ? 0 : currentIndex + 1)
|
||
|
listView.currentIndex = currentIndex
|
||
|
if (listView.currentItem.visible) {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
listView.currentIndex = 0
|
||
|
}
|
||
|
|
||
|
Keys.onReleased: {
|
||
|
listView.selectByHover = false
|
||
|
|
||
|
if (event.key === Qt.Key_Down) {
|
||
|
searchBox.goToNextAvailableIndex(false)
|
||
|
}
|
||
|
if (event.key === Qt.Key_Up) {
|
||
|
searchBox.goToNextAvailableIndex(true)
|
||
|
}
|
||
|
if (event.key === Qt.Key_Escape) {
|
||
|
return root.close()
|
||
|
}
|
||
|
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
|
||
|
return root.selected(listView.currentIndex,
|
||
|
listView.currentItem.myData)
|
||
|
}
|
||
|
if (!listView.currentItem.visible) {
|
||
|
goToNextAvailableIndex(false)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onTextChanged: if (text === "") listView.currentIndex = 0
|
||
|
}
|
||
|
|
||
|
ListView {
|
||
|
id: listView
|
||
|
|
||
|
Layout.fillWidth: true
|
||
|
Layout.fillHeight: true
|
||
|
|
||
|
property bool selectByHover: false
|
||
|
|
||
|
clip: true
|
||
|
highlightMoveDuration: 200
|
||
|
|
||
|
delegate: Item {
|
||
|
id: delegateItem
|
||
|
|
||
|
property var myData: typeof modelData === "undefined" ? model : modelData
|
||
|
|
||
|
width: listView.width
|
||
|
height: visible ? delegateLoader.height : 0
|
||
|
|
||
|
Loader {
|
||
|
id: delegateLoader
|
||
|
|
||
|
width: parent.width
|
||
|
sourceComponent: root.delegate
|
||
|
|
||
|
onLoaded: {
|
||
|
item.modelData = delegateItem.myData
|
||
|
item.isCurrentItem = Qt.binding(() => delegateItem.ListView.isCurrentItem)
|
||
|
delegateItem.visible = Qt.binding(() => item.filterAccepts(searchBox.text))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MouseArea {
|
||
|
anchors.fill: parent
|
||
|
|
||
|
hoverEnabled: true
|
||
|
onClicked: (mouse) => {
|
||
|
listView.currentIndex = index
|
||
|
root.selected(index, delegateItem.myData)
|
||
|
mouse.accepted = false
|
||
|
}
|
||
|
onContainsMouseChanged: if (containsMouse) listView.currentIndex = index
|
||
|
cursorShape: Qt.PointingHandCursor
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Loader {
|
||
|
anchors.fill: parent
|
||
|
active: !listView.selectByHover
|
||
|
|
||
|
sourceComponent: MouseArea {
|
||
|
hoverEnabled: true
|
||
|
onPositionChanged: listView.selectByHover = true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
onAboutToShow: {
|
||
|
listView.currentIndex = 0
|
||
|
listView.selectByHover = false
|
||
|
searchBox.text = ""
|
||
|
searchBox.input.edit.forceActiveFocus()
|
||
|
}
|
||
|
}
|