// SPDX-FileCopyrightText: 2023 Tobias Fella // SPDX-FileCopyrightText: 2024 Carl Schwan // SPDX-License-Identifier: LGPL-2.0-or-later pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls as QQC2 import QtQuick.Layouts import org.kde.kirigami as Kirigami /*! \qmltype SearchDialog \inqmlmodule org.kde.kirigami.dialogs \brief A dialog to let's you do a global search across your applications documents, chat rooms and more. Example usage for a chat app where we want to quickly search for a room. \qml import QtQuick import org.kde.kitemmodels as KItemModels import org.kde.kirigami as Kirigami Kirigami.SearchDialog { id: root onTextChanged: { sortModel.filterString = text; } onAccepted: listView.currentItem.clicked() emptyText: i18nc("Placeholder message", "No room found.") model: KItemModels.KSortFilterProxyModel { id: sortModel sourceModel: RoomModel { } } delegate: RoomDelegate { onClicked: root.close() } Shortcut { sequence: "Ctrl+K" onActivated: root.open() } } \endqml \image searchdialog.png \note This component is unsuitable on mobile. Instead on mobile prefer to use a separate page for the search. \note By default, the title and standardButtons property are ignored. \since 6.3 */ QQC2.Dialog { id: root /*! \qmlproperty model SearchDialog::model This property holds an alias to the model of the internal ListView. */ property alias model: listView.model /*! \qmlproperty Component SearchDialog::delegate This property holds an alias to the delegate component of the internal ListView. */ property alias delegate: listView.delegate /*! \qmlproperty Item SearchDialog::currentItem This property holds an alias to the currentItem component of the internal ListView. */ property alias currentItem: listView.currentItem /*! \qmlproperty enumeration SearchDialog::section.criteria \qmlproperty Component SearchDialog::section.delegate \qmlproperty enumneration SearchDialog::section.labelPositioning \qmlproperty string SearchDialog::section.property This property holds an alias to the section component of the internal ListView. */ property alias section: listView.section /*! \qmlproperty string SearchDialog::text This property holds an alias to the content of the search field. */ property alias text: searchField.text /*! \qmlproperty list SearchDialog::searchFieldLeftActions This property holds an alias to the left actions of the search field. \sa ActionTextField::leftActions */ property alias searchFieldLeftActions: searchField.leftActions /*! \qmlproperty list SearchDialog::searchFieldRightActions This property holds an alias to the right actions of the search field. \sa ActionTextField::rightActions */ property alias searchFieldRightActions: searchField.rightActions /*! \qmlproperty string SearchDialog::searchFieldPlaceholderText The placeholder text shown in the (empty) search field. */ property alias searchFieldPlaceholderText: searchField.placeholderText /*! \qmlproperty int SearchDialog::count This property holds the number of search results displayed in the internal ListView. */ property alias count: listView.count /*! \qmlproperty string SearchDialog::emptyText This property holds an alias to the placeholder message text displayed when the internal list view is empty. */ property alias emptyText: placeholder.text /*! \qmlproperty string SearchDialog::emptyIcon.name \qmlproperty string SearchDialog::emptyIcon.source \qmlproperty int SearchDialog::emptyIcon.width \qmlproperty int SearchDialog::emptyIcon.height \qmlproperty color SearchDialog::emptyIcon.color This property holds an alias to the placeholder message icon displayed when the internal list view is empty. */ property alias emptyIcon: placeholder.icon /*! \qmlproperty Action SearchDialog::emptyHelpfulAction \brief Helpful action when the list is empty This property holds an alias to the helpful action of the placeholder message when the internal list view is empty. \since 6.10 */ property alias emptyHelpfulAction: placeholder.helpfulAction width: Math.min(Kirigami.Units.gridUnit * 35, parent.width - leftMargin - rightMargin) height: Math.min(Kirigami.Units.gridUnit * 20, parent.height) padding: 0 header: null footer: null standardButtons: QQC2.Dialog.NoButton anchors.centerIn: parent modal: true onOpened: { searchField.forceActiveFocus(); searchField.text = ""; listView.currentIndex = 0; } contentItem: ColumnLayout { spacing: 0 Kirigami.SearchField { id: searchField Layout.fillWidth: true background: null Layout.margins: Kirigami.Units.smallSpacing Keys.onDownPressed: { const listViewHadFocus = listView.activeFocus; listView.forceActiveFocus(); if (listView.currentIndex < listView.count - 1) { // don't move to the next entry when we just changed focus from the search field to the list view if (listViewHadFocus) { listView.currentIndex++; } } else { listView.currentIndex = 0; } } Keys.onUpPressed: { listView.forceActiveFocus(); if (listView.currentIndex === 0) { listView.currentIndex = listView.count - 1; } else { listView.currentIndex--; } } Keys.onPressed: (event) => { switch (event.key) { case Qt.Key_PageDown: listView.forceActiveFocus(); listView.currentIndex = Math.min(listView.count - 1, listView.currentIndex + Math.floor(listView.height / listView.currentItem.height)); event.accepted = true; break; case Qt.Key_PageUp: listView.forceActiveFocus(); listView.currentIndex = Math.max(0, listView.currentIndex - Math.floor(listView.height / listView.currentItem.height)); event.accepted = true; break; } } focusSequence: "" focusSequences: [] autoAccept: false onAccepted: root.accepted() } Kirigami.Separator { Layout.fillWidth: true } QQC2.ScrollView { Layout.fillWidth: true Layout.fillHeight: true Keys.forwardTo: searchField ListView { id: listView currentIndex: 0 clip: true highlightMoveDuration: 200 Keys.forwardTo: searchField keyNavigationEnabled: true Kirigami.PlaceholderMessage { id: placeholder anchors.centerIn: parent width: parent.width - Kirigami.Units.gridUnit * 4 icon.name: 'system-search-symbolic' visible: listView.count === 0 && text.length > 0 } } } } }