Warning, /multimedia/kasts/src/qml/GlobalSearchField.qml is written in an unsupported language. File is not indexed.
0001 /** 0002 * SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 import QtQuick 0008 import QtQuick.Controls as Controls 0009 import QtQuick.Layouts 0010 import QtQml.Models 0011 0012 import org.kde.kirigami as Kirigami 0013 import org.kde.kirigamiaddons.labs.components as Addons 0014 import org.kde.kirigamiaddons.delegates as AddonDelegates 0015 import org.kde.kirigami.delegates as Delegates 0016 0017 import org.kde.kasts 0018 0019 Addons.SearchPopupField { 0020 id: globalSearchField 0021 spaceAvailableLeft: false 0022 spaceAvailableRight: true 0023 0024 autoAccept: false 0025 0026 popup.width: Math.min(Kirigami.Units.gridUnit * 20, kastsMainWindow.width - Kirigami.Units.gridUnit * 2) 0027 0028 property string searchFilter: "" 0029 0030 onAccepted: { 0031 globalSearchField.searchFilter = globalSearchField.text 0032 } 0033 0034 popup.onClosed: { 0035 globalSearchField.text = "" 0036 } 0037 0038 onTextChanged: { 0039 if (globalSearchField.text === "") { 0040 globalSearchField.searchFilter = ""; 0041 } 0042 } 0043 0044 function openEntry(entry) { 0045 pushPage("EpisodeListPage"); 0046 pageStack.push("qrc:/qt/qml/org/kde/kasts/qml/EntryPage.qml", {"entry": entry}); 0047 0048 // Find the index of the entry on the EpisodeListPage and scroll to it 0049 var episodeModel = pageStack.get(0).episodeList.model 0050 for (var i = 0; i < episodeModel.rowCount(); i++) { 0051 var index = episodeModel.index(i, 0); 0052 if (entry.id == episodeModel.data(index, AbstractEpisodeModel.IdRole)) { 0053 pageStack.get(0).episodeList.currentIndex = i; 0054 pageStack.get(0).episodeList.selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Rows); 0055 pageStack.get(0).episodeList.positionViewAtIndex(i, ListView.Center); 0056 } 0057 } 0058 } 0059 0060 Component.onCompleted: { 0061 // rightActions are defined from right-to-left 0062 // if we want to insert the settings action as the rightmost, then it 0063 // must be defined as first action, which means that we need to save the 0064 // default clear action and push that as a second action 0065 var origAction = searchField.rightActions[0]; 0066 searchField.rightActions[0] = searchSettingsButton; 0067 searchField.rightActions.push(origAction); 0068 } 0069 0070 ListView { 0071 id: searchListView 0072 reuseItems: true 0073 0074 EpisodeProxyModel { 0075 id: proxyModel 0076 searchFilter: globalSearchField.searchFilter 0077 } 0078 0079 model: globalSearchField.searchFilter === "" ? null : proxyModel 0080 0081 delegate: AddonDelegates.RoundedItemDelegate { 0082 contentItem: Delegates.IconTitleSubtitle { 0083 icon.source: model.entry.cachedImage 0084 title: model.entry.title 0085 subtitle: model.entry.feed.name 0086 } 0087 onClicked: { 0088 globalSearchField.openEntry(model.entry); 0089 globalSearchField.popup.close(); 0090 } 0091 } 0092 0093 Kirigami.PlaceholderMessage { 0094 id: loadingPlaceholder 0095 anchors.fill: parent 0096 visible: searchListView.count === 0 0097 0098 text: i18nc("@info Placeholder text in search box", "No search results") 0099 } 0100 0101 Kirigami.Action { 0102 id: searchSettingsButton 0103 visible: globalSearchField.popup.visible 0104 icon.name: "settings-configure" 0105 text: i18nc("@action:intoolbar", "Advanced Search Options") 0106 0107 onTriggered: { 0108 if (searchSettingsMenu.visible) { 0109 searchSettingsMenu.dismiss(); 0110 } else { 0111 searchSettingsMenu.popup(searchSettingsButton); 0112 } 0113 } 0114 } 0115 0116 ListModel { 0117 id: searchSettingsModel 0118 0119 function reload() { 0120 clear(); 0121 var searchList = [AbstractEpisodeProxyModel.TitleFlag, 0122 AbstractEpisodeProxyModel.ContentFlag, 0123 AbstractEpisodeProxyModel.FeedNameFlag] 0124 for (var i in searchList) { 0125 searchSettingsModel.append({"name": proxyModel.getSearchFlagName(searchList[i]), 0126 "searchFlag": searchList[i], 0127 "checked": proxyModel.searchFlags & searchList[i]}); 0128 } 0129 } 0130 0131 Component.onCompleted: { 0132 reload(); 0133 } 0134 } 0135 0136 Controls.Menu { 0137 id: searchSettingsMenu 0138 0139 title: i18nc("@title:menu", "Search Preferences") 0140 0141 Controls.Label { 0142 padding: Kirigami.Units.smallSpacing 0143 text: i18nc("@title:group Group of fields in which can be searched", "Search in:") 0144 } 0145 0146 Repeater { 0147 model: searchSettingsModel 0148 0149 Controls.MenuItem { 0150 text: model.name 0151 checkable: true 0152 checked: model.checked 0153 onTriggered: { 0154 if (checked) { 0155 proxyModel.searchFlags = proxyModel.searchFlags | model.searchFlag; 0156 } else { 0157 proxyModel.searchFlags = proxyModel.searchFlags & ~model.searchFlag; 0158 } 0159 } 0160 } 0161 } 0162 0163 onOpened: { 0164 searchSettingsModel.reload(); 0165 } 0166 } 0167 } 0168 }