Warning, /plasma/discover/discover/qml/ApplicationsListPage.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2012 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 pragma ComponentBehavior: Bound 0008 0009 import QtQuick 0010 import QtQuick.Controls as QQC2 0011 import QtQuick.Layouts 0012 import org.kde.kirigami as Kirigami 0013 import org.kde.discover as Discover 0014 import org.kde.discover.app as DiscoverApp 0015 0016 DiscoverPage { 0017 id: page 0018 0019 readonly property var model: appsModel 0020 property alias category: appsModel.filteredCategory 0021 property alias sortRole: appsModel.sortRole 0022 property alias sortOrder: appsModel.sortOrder 0023 property alias originFilter: appsModel.originFilter 0024 property alias mimeTypeFilter: appsModel.mimeTypeFilter 0025 property alias stateFilter: appsModel.stateFilter 0026 property alias extending: appsModel.extending 0027 property alias search: appsModel.search 0028 property alias resourcesUrl: appsModel.resourcesUrl 0029 property alias busy: appsModel.busy 0030 property alias allBackends: appsModel.allBackends 0031 property alias count: appsView.count 0032 property alias listHeader: appsView.header 0033 property alias listHeaderPositioning: appsView.headerPositioning 0034 property string sortProperty: "appsListPageSorting" 0035 property bool showRating: true 0036 property bool showSize: false 0037 property bool searchPage: false 0038 0039 property bool canNavigate: true 0040 readonly property alias subcategories: appsModel.subcategories 0041 0042 function stripHtml(input) { 0043 var regex = /(<([^>]+)>)/ig 0044 return input.replace(regex, ""); 0045 } 0046 0047 property string name: category?.name ?? "" 0048 0049 title: { 0050 const count = appsModel.count; 0051 if (search.length > 0 && count.number > 0) { 0052 if (count.valid) { 0053 return i18np("Search: %2 - %3 item", "Search: %2 - %3 items", count.number, stripHtml(search), count.string) 0054 } else { 0055 return i18n("Search: %1", stripHtml(search)) 0056 } 0057 } else if (name.length > 0 && count.number > 0) { 0058 if (count.valid) { 0059 return i18np("%2 - %1 item", "%2 - %1 items", count.number, name) 0060 } else { 0061 return name 0062 } 0063 } else { 0064 if (count.valid && count.number > 0) { 0065 return i18np("Search - %1 item", "Search - %1 items", count.number) 0066 } else { 0067 return i18n("Search") 0068 } 0069 } 0070 } 0071 0072 signal clearSearch() 0073 0074 Kirigami.Theme.colorSet: Kirigami.Theme.Window 0075 Kirigami.Theme.inherit: false 0076 0077 onSearchChanged: { 0078 if (search.length > 0) { 0079 appsModel.tempSortRole = Discover.ResourcesProxyModel.SearchRelevanceRole 0080 } else { 0081 appsModel.tempSortRole = -1 0082 } 0083 } 0084 0085 supportsRefreshing: true 0086 onRefreshingChanged: if (refreshing) { 0087 appsModel.invalidateFilter() 0088 refreshing = false 0089 } 0090 0091 QQC2.ActionGroup { 0092 id: sortGroup 0093 exclusive: true 0094 } 0095 0096 actions: [ 0097 Kirigami.Action { 0098 text: i18n("Sort: %1", sortGroup.checkedAction.text) 0099 icon.name: "view-sort" 0100 Kirigami.Action { 0101 visible: appsModel.search.length > 0 0102 QQC2.ActionGroup.group: sortGroup 0103 text: i18nc("Search results most relevant to the search query", "Relevance") 0104 icon.name: "file-search-symbolic" 0105 onTriggered: { 0106 // Do *not* save the sort role on searches 0107 appsModel.tempSortRole = Discover.ResourcesProxyModel.SearchRelevanceRole 0108 } 0109 checkable: true 0110 checked: appsModel.sortRole === Discover.ResourcesProxyModel.SearchRelevanceRole 0111 } 0112 Kirigami.Action { 0113 QQC2.ActionGroup.group: sortGroup 0114 text: i18n("Name") 0115 icon.name: "sort-name" 0116 onTriggered: { 0117 DiscoverApp.DiscoverSettings[page.sortProperty] = Discover.ResourcesProxyModel.NameRole 0118 appsModel.tempSortRole = -1 0119 } 0120 checkable: true 0121 checked: appsModel.sortRole === Discover.ResourcesProxyModel.NameRole 0122 } 0123 Kirigami.Action { 0124 QQC2.ActionGroup.group: sortGroup 0125 text: i18n("Rating") 0126 icon.name: "rating" 0127 onTriggered: { 0128 DiscoverApp.DiscoverSettings[page.sortProperty] = Discover.ResourcesProxyModel.SortableRatingRole 0129 appsModel.tempSortRole = -1 0130 } 0131 checkable: true 0132 checked: appsModel.sortRole === Discover.ResourcesProxyModel.SortableRatingRole 0133 } 0134 Kirigami.Action { 0135 QQC2.ActionGroup.group: sortGroup 0136 text: i18n("Size") 0137 icon.name: "download" 0138 onTriggered: { 0139 DiscoverApp.DiscoverSettings[page.sortProperty] = Discover.ResourcesProxyModel.SizeRole 0140 appsModel.tempSortRole = -1 0141 } 0142 checkable: true 0143 checked: appsModel.sortRole === Discover.ResourcesProxyModel.SizeRole 0144 } 0145 Kirigami.Action { 0146 QQC2.ActionGroup.group: sortGroup 0147 text: i18n("Release Date") 0148 icon.name: "change-date-symbolic" 0149 onTriggered: { 0150 DiscoverApp.DiscoverSettings[page.sortProperty] = Discover.ResourcesProxyModel.ReleaseDateRole 0151 appsModel.tempSortRole = -1 0152 } 0153 checkable: true 0154 checked: appsModel.sortRole === Discover.ResourcesProxyModel.ReleaseDateRole 0155 } 0156 } 0157 ] 0158 0159 Kirigami.CardsListView { 0160 id: appsView 0161 activeFocusOnTab: true 0162 currentIndex: -1 0163 onActiveFocusChanged: if (activeFocus && currentIndex === -1) { 0164 currentIndex = 0; 0165 } 0166 0167 model: Discover.ResourcesProxyModel { 0168 id: appsModel 0169 property int tempSortRole: -1 0170 sortRole: tempSortRole >= 0 ? tempSortRole : DiscoverApp.DiscoverSettings.appsListPageSorting 0171 sortOrder: sortRole === Discover.ResourcesProxyModel.NameRole ? Qt.AscendingOrder : Qt.DescendingOrder 0172 0173 onBusyChanged: { 0174 if (busy) { 0175 appsView.currentIndex = -1 0176 } 0177 } 0178 } 0179 0180 delegate: ApplicationDelegate { 0181 compact: !applicationWindow().wideScreen 0182 showRating: page.showRating 0183 showSize: page.showSize 0184 } 0185 0186 Item { 0187 readonly property bool nothingFound: appsView.count == 0 && !appsModel.busy && !Discover.ResourcesModel.isInitializing && (!page.searchPage || appsModel.search.length > 0) 0188 0189 anchors.fill: parent 0190 opacity: nothingFound ? 1 : 0 0191 visible: opacity > 0 0192 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad } } 0193 0194 Kirigami.PlaceholderMessage { 0195 visible: !searchedForThingNotFound.visible 0196 anchors.centerIn: visible ? parent : undefined 0197 width: parent.width - (Kirigami.Units.largeSpacing * 8) 0198 0199 icon.name: "edit-none" 0200 text: i18n("Nothing found") 0201 } 0202 0203 Kirigami.PlaceholderMessage { 0204 id: searchedForThingNotFound 0205 0206 Kirigami.Action { 0207 id: searchAllCategoriesAction 0208 text: i18nc("@action:button", "Search in All Categories") 0209 icon.name: "search" 0210 onTriggered: { 0211 window.globalDrawer.resetMenu(); 0212 Navigation.clearStack() 0213 Navigation.openApplicationList({ search: page.search }); 0214 } 0215 } 0216 Kirigami.Action { 0217 id: searchTheWebAction 0218 text: i18nc("@action:button %1 is the name of an application", "Search the Web for \"%1\"", appsModel.search) 0219 icon.name: "internet-web-browser" 0220 onTriggered: { 0221 const searchTerm = encodeURIComponent("Linux " + appsModel.search); 0222 Qt.openUrlExternally(i18nc("If appropriate, localize this URL to be something more relevant to the language. %1 is the text that will be searched for.", "https://duckduckgo.com/?q=%1", searchTerm)); 0223 } 0224 } 0225 0226 anchors.centerIn: parent 0227 width: parent.width - (Kirigami.Units.largeSpacing * 8) 0228 0229 visible: appsModel.search.length > 0 && stateFilter !== Discover.AbstractResource.Installed 0230 0231 icon.name: "edit-none" 0232 text: page.category ? i18nc("@info:placeholder %1 is the name of an application; %2 is the name of a category of apps or add-ons", 0233 "\"%1\" was not found in the \"%2\" category", appsModel.search, page.category.name) 0234 : i18nc("@info:placeholder %1 is the name of an application", 0235 "\"%1\" was not found in the available sources", appsModel.search) 0236 explanation: page.category ? "" : i18nc("@info:placeholder %1 is the name of an application", "\"%1\" may be available on the web. Software acquired from the web has not been reviewed by your distributor for functionality or stability. Use with caution.", appsModel.search) 0237 0238 // If we're in a category, first direct the user to search globally, 0239 // because they might not have realized they were in a category and 0240 // therefore the results were limited to just what was in the category 0241 helpfulAction: page.category ? searchAllCategoriesAction : searchTheWebAction 0242 } 0243 } 0244 0245 Kirigami.PlaceholderMessage { 0246 anchors.centerIn: parent 0247 width: parent.width - (Kirigami.Units.largeSpacing * 4) 0248 0249 visible: opacity !== 0 0250 opacity: appsView.count === 0 && page.searchPage && appsModel.search.length === 0 ? 1 : 0 0251 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad } } 0252 0253 icon.name: "search" 0254 text: i18n("Search") 0255 } 0256 0257 footer: ColumnLayout { 0258 visible: appsModel.busy && appsView.atYEnd 0259 opacity: visible ? 0.5 : 0 0260 height: visible ? Layout.preferredHeight : 0 0261 width: appsView.width 0262 0263 Item { 0264 Layout.preferredHeight: Kirigami.Units.gridUnit 0265 } 0266 Kirigami.Heading { 0267 level: 2 0268 Layout.alignment: Qt.AlignCenter 0269 text: i18n("Still looking…") 0270 } 0271 QQC2.BusyIndicator { 0272 running: parent.visible 0273 Layout.alignment: Qt.AlignCenter 0274 Layout.preferredWidth: Kirigami.Units.gridUnit * 4 0275 Layout.preferredHeight: Kirigami.Units.gridUnit * 4 0276 } 0277 Behavior on opacity { 0278 PropertyAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad } 0279 } 0280 } 0281 } 0282 }