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 }