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 }