diff --git a/discover/qml/ActionListItem.qml b/discover/qml/ActionListItem.qml index d969ff06..f971f82b 100644 --- a/discover/qml/ActionListItem.qml +++ b/discover/qml/ActionListItem.qml @@ -1,35 +1,36 @@ /*************************************************************************** * Copyright © 2015 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ import QtQml 2.0 import QtQuick.Controls 2.0 import org.kde.kirigami 2.0 as Kirigami Kirigami.BasicListItem { property QtObject action: null checked: action.checked icon: action.iconName label: action.text separatorVisible: false + visible: action.enabled onClicked: { drawer.resetMenu() action.trigger() } } diff --git a/discover/qml/ApplicationsListPage.qml b/discover/qml/ApplicationsListPage.qml index f7c8619e..2724b010 100644 --- a/discover/qml/ApplicationsListPage.qml +++ b/discover/qml/ApplicationsListPage.qml @@ -1,157 +1,160 @@ /* * Copyright (C) 2012 Aleix Pol Gonzalez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library/Lesser General Public License * version 2, or (at your option) any later version, as published by the * Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library/Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.5 import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import "navigation.js" as Navigation import org.kde.discover.app 1.0 import org.kde.discover 2.0 import org.kde.kirigami 2.0 as Kirigami DiscoverPage { id: page readonly property var model: appsModel property alias category: appsModel.filteredCategory property alias sortRole: appsModel.sortRole property alias sortOrder: appsModel.sortOrder property alias originFilter: appsModel.originFilter property alias mimeTypeFilter: appsModel.mimeTypeFilter property alias stateFilter: appsModel.stateFilter property alias extend: appsModel.extends property alias search: appsModel.search property alias resourcesUrl: appsModel.resourcesUrl property alias isBusy: appsModel.isBusy property alias allBackends: appsModel.allBackends property alias count: apps.count property alias listHeader: apps.header + property Component listHeaderExtra property bool compact: page.width < 500 || !applicationWindow().wideScreen property bool canNavigate: true readonly property alias subcategories: appsModel.subcategories title: category ? category.name : "" onSearchChanged: { if (search.length === 0) Navigation.openHome() appsModel.sortOrder = Qt.AscendingOrder } signal clearSearch() ListView { id: apps section.delegate: Label { text: section anchors { right: parent.right } } headerPositioning: ListView.OverlayHeader header: CategoryDisplay { + id: header category: appsModel.filteredCategory search: appsModel.search + extra: page.listHeaderExtra } model: ResourcesProxyModel { id: appsModel sortRole: ResourcesProxyModel.RatingCountRole sortOrder: Qt.DescendingOrder } spacing: Kirigami.Units.gridUnit currentIndex: -1 delegate: ApplicationDelegate { x: Kirigami.Units.gridUnit width: ListView.view.width - Kirigami.Units.gridUnit*2 application: model.application compact: page.compact } Kirigami.Label { anchors.centerIn: parent opacity: apps.count == 0 && !appsModel.isBusy ? 0.3 : 0 Behavior on opacity { PropertyAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad; } } text: i18n("Sorry, nothing found...") } BusyIndicator { id: busyIndicator anchors { top: parent.bottom horizontalCenter: parent.horizontalCenter margins: Kirigami.Units.largeSpacing } running: false opacity: 0 states: [ State { name: "running"; when: appsModel.isBusy PropertyChanges { target: busyIndicator; opacity: 1; running: true; } AnchorChanges { target: busyIndicator; anchors.bottom: parent.bottom; anchors.top: undefined; } } ] transitions: [ Transition { from: "" to: "running" SequentialAnimation { PauseAnimation { duration: Kirigami.Units.longDuration * 5; } ParallelAnimation { AnchorAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad; } PropertyAnimation { property: "opacity"; duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad; } } } }, Transition { from: "running" to: "" ParallelAnimation { AnchorAnimation { duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad; } PropertyAnimation { property: "opacity"; duration: Kirigami.Units.shortDuration; easing.type: Easing.InOutQuad; } } } ] Kirigami.Label { id: busyLabel anchors { horizontalCenter: parent.horizontalCenter bottom: parent.top } text: i18n("Still looking...") opacity: 0 states: [ State { name: "running"; when: busyIndicator.opacity === 1; PropertyChanges { target: busyLabel; opacity: 1; } } ] transitions: Transition { from: "" to: "running" SequentialAnimation { PauseAnimation { duration: Kirigami.Units.longDuration * 5; } PropertyAnimation { property: "opacity"; duration: Kirigami.Units.longDuration * 10; easing.type: Easing.InOutCubic; } } } } } } } diff --git a/discover/qml/DiscoverDrawer.qml b/discover/qml/DiscoverDrawer.qml index d6e418c5..7489ca50 100644 --- a/discover/qml/DiscoverDrawer.qml +++ b/discover/qml/DiscoverDrawer.qml @@ -1,194 +1,199 @@ /*************************************************************************** * Copyright © 2015 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ import QtQuick 2.5 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.1 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import org.kde.kirigami 2.0 as Kirigami import "navigation.js" as Navigation Kirigami.GlobalDrawer { id: drawer property bool wideScreen: false bannerImageSource: "qrc:/banners/banner.svg" //make the left and bottom margins for search field the same - topPadding: -searchField.height - leftPadding + topPadding: searchField.visible ? -searchField.height - leftPadding : 0 bottomPadding: 0 resetMenuOnTriggered: false onBannerClicked: { Navigation.openHome(); } function clearSearch() { searchField.text = "" } onCurrentSubMenuChanged: { if (currentSubMenu) currentSubMenu.trigger() else if (searchField.text !== "") window.leftPage.category = null else Navigation.openHome() } - topContent: TextField { + topContent: drawer.wideScreen ? searchField : null + TextField { id: searchField Layout.fillWidth: true + visible: drawer.wideScreen enabled: window.leftPage && (window.leftPage.searchFor != null || window.leftPage.hasOwnProperty("search")) Keys.forwardTo: [window.pageStack] Component.onCompleted: { searchField.forceActiveFocus() } Shortcut { sequence: "Ctrl+F" onActivated: { searchField.forceActiveFocus() searchField.selectAll() } } placeholderText: (!enabled || !window.leftPage || window.leftPage.title.length === 0) ? i18n("Search...") : i18n("Search in '%1'...", window.leftPage.title) onTextChanged: { if(window.stack.depth > 0) searchTimer.running = true } Connections { ignoreUnknownSignals: true target: window.leftPage onClearSearch: { drawer.clearSearch() } } Timer { id: searchTimer running: false repeat: false interval: 200 onTriggered: { var curr = window.leftPage; if (!curr.hasOwnProperty("search")) { Navigation.clearStack() Navigation.openApplicationList( { search: parent.text }) } else curr.search = parent.text; } } } ColumnLayout { spacing: 0 Layout.fillWidth: true Layout.leftMargin: -drawer.leftPadding Layout.rightMargin: -drawer.rightPadding Kirigami.Separator { Layout.fillWidth: true } ProgressView { separatorVisible: false } + ActionListItem { + action: searchAction + } ActionListItem { action: installedAction } ActionListItem { action: settingsAction } ActionListItem { objectName: "updateButton" action: updateAction backgroundColor: ResourcesModel.updatesCount>0 ? "orange" : Kirigami.Theme.viewBackgroundColor } states: [ State { name: "full" when: drawer.wideScreen PropertyChanges { target: drawer; drawerOpen: true } }, State { name: "compact" when: !drawer.wideScreen PropertyChanges { target: drawer; drawerOpen: false } } ] } function rootCategory(cat) { var ret = null while (cat) { ret = cat cat = cat.parent } return ret } Component { id: categoryActionComponent Kirigami.Action { property QtObject category readonly property bool itsMe: window.leftPage && window.leftPage.hasOwnProperty("category") && (window.leftPage.category == category) text: category.name checked: itsMe visible: (!window.leftPage || !window.leftPage.subcategories || window.leftPage.subcategories === undefined || searchField.text.length === 0 || (category && category.contains(window.leftPage.subcategories)) ) onTriggered: { if (!window.leftPage.canNavigate) Navigation.openCategory(category, searchField.text) else { window.leftPage.category = category pageStack.currentIndex = 0 } } } } function createCategoryActions(categories) { var actions = [] for(var i in categories) { var cat = categories[i]; var catAction = categoryActionComponent.createObject(drawer, {category: cat}); catAction.children = createCategoryActions(cat.subcategories); actions.push(catAction) } return actions; } actions: createCategoryActions(CategoryModel.rootCategories) modal: !drawer.wideScreen handleVisible: !drawer.wideScreen } diff --git a/discover/qml/DiscoverWindow.qml b/discover/qml/DiscoverWindow.qml index 51757ebb..2c453dff 100644 --- a/discover/qml/DiscoverWindow.qml +++ b/discover/qml/DiscoverWindow.qml @@ -1,176 +1,187 @@ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.1 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import org.kde.kirigami 2.0 as Kirigami import "navigation.js" as Navigation Kirigami.ApplicationWindow { id: window readonly property string applicationListComp: ("qrc:/qml/ApplicationsListPage.qml") readonly property string applicationComp: ("qrc:/qml/ApplicationPage.qml") readonly property string reviewsComp: ("qrc:/qml/ReviewsPage.qml") //toplevels readonly property string topBrowsingComp: ("qrc:/qml/BrowsingPage.qml") readonly property string topInstalledComp: ("qrc:/qml/InstalledPage.qml") + readonly property string topSearchComp: ("qrc:/qml/SearchPage.qml") readonly property string topUpdateComp: ("qrc:/qml/UpdatesPage.qml") readonly property string topSourcesComp: ("qrc:/qml/SourcesPage.qml") readonly property string loadingComponent: ("qrc:/qml/LoadingPage.qml") readonly property QtObject stack: window.pageStack property string currentTopLevel: defaultStartup ? topBrowsingComp : loadingComponent property bool defaultStartup: true objectName: "DiscoverMainWindow" title: leftPage ? leftPage.title : "" header: null visible: true minimumWidth: 300 minimumHeight: 300 pageStack.defaultColumnWidth: Kirigami.Units.gridUnit * 25 readonly property var leftPage: window.stack.depth>0 ? window.stack.get(0) : null Component.onCompleted: { if (app.isRoot) showPassiveNotification(i18n("Running as root is discouraged and unnecessary.")); } TopLevelPageData { iconName: "tools-wizard" text: i18n("Discover") component: topBrowsingComp objectName: "discover" shortcut: "Alt+D" } + + TopLevelPageData { + id: searchAction + enabled: !window.wideScreen + iconName: "search" + text: i18n("Search") + component: topSearchComp + objectName: "discover" + shortcut: "Ctrl+F" + } TopLevelPageData { id: installedAction text: i18n("Installed") component: topInstalledComp objectName: "installed" shortcut: "Alt+I" } TopLevelPageData { id: updateAction iconName: enabled ? "update-low" : "update-none" text: ResourcesModel.updatesCount<=0 ? (ResourcesModel.isFetching ? i18n("Checking for updates...") : i18n("No Updates") ) : i18nc("Update section name", "Update (%1)", ResourcesModel.updatesCount) component: topUpdateComp objectName: "update" shortcut: "Alt+U" } TopLevelPageData { id: settingsAction iconName: "settings" text: i18n("Settings") component: topSourcesComp objectName: "settings" shortcut: "Alt+S" } Connections { target: app onOpenApplicationInternal: { Navigation.clearStack() Navigation.openApplication(app) } onOpenUrl: { currentTopLevel = topBrowsingComp; Navigation.openUrlResources(url) } onListMimeInternal: { currentTopLevel = topBrowsingComp; Navigation.openApplicationMime(mime) } onListCategoryInternal: { currentTopLevel = topBrowsingComp; Navigation.openCategory(cat, "") } onPreventedClose: showPassiveNotification(i18n("Could not close the application, there are tasks that need to be done."), 3000) onUnableToFind: { showPassiveNotification(i18n("Unable to find resource: %1", resid)); Navigation.openHome() } } Connections { target: ResourcesModel onPassiveMessage: { showPassiveNotification(message, 3000) console.log("message:", message) } } Component { id: proceedDialog Kirigami.OverlaySheet { id: sheet property QtObject transaction property alias title: heading.text property alias description: desc.text property bool acted: false ColumnLayout { Kirigami.Heading { id: heading } Kirigami.Label { id: desc Layout.fillWidth: true wrapMode: Text.WordWrap } Button { Layout.alignment: Qt.AlignRight iconName: "dialog-ok" onClicked: { transaction.proceed() sheet.acted = true sheet.close() } } } onSheetOpenChanged: if(!sheetOpen) { sheet.destroy(1000) if (!sheet.acted) transaction.cancel() } } } Instantiator { model: TransactionModel delegate: Connections { target: model.transaction ? model.transaction : null onProceedRequest: { var dialog = proceedDialog.createObject(window, {transaction: transaction, title: title, description: description}) dialog.open() } onPassiveMessage: { window.showPassiveNotification(message) } } } globalDrawer: DiscoverDrawer { wideScreen: window.wideScreen focus: true } onCurrentTopLevelChanged: { window.pageStack.clear() if (currentTopLevel) window.pageStack.push(currentTopLevel, {}, window.status!=Component.Ready) } UnityLauncher { launcherId: "org.kde.discover.desktop" progressVisible: TransactionModel.count > 0 progress: TransactionModel.progress } } diff --git a/discover/qml/ActionListItem.qml b/discover/qml/SearchPage.qml similarity index 78% copy from discover/qml/ActionListItem.qml copy to discover/qml/SearchPage.qml index d969ff06..a4476a8a 100644 --- a/discover/qml/ActionListItem.qml +++ b/discover/qml/SearchPage.qml @@ -1,35 +1,31 @@ /*************************************************************************** - * Copyright © 2015 Aleix Pol Gonzalez * + * Copyright © 2017 Aleix Pol Gonzalez * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ -import QtQml 2.0 -import QtQuick.Controls 2.0 -import org.kde.kirigami 2.0 as Kirigami +import QtQuick.Controls 1.1 +import org.kde.discover 2.0 -Kirigami.BasicListItem { - property QtObject action: null - checked: action.checked - icon: action.iconName - label: action.text - separatorVisible: false - onClicked: { - drawer.resetMenu() - action.trigger() +ApplicationsListPage { + id: page + + listHeaderExtra: TextField { + focus: true + onTextChanged: page.search = text } } diff --git a/discover/resources.qrc b/discover/resources.qrc index 32475fdc..05ce5dcb 100644 --- a/discover/resources.qrc +++ b/discover/resources.qrc @@ -1,38 +1,39 @@ qml/TopLevelPageData.qml qml/CategoryDisplay.qml qml/ApplicationsListPage.qml qml/ApplicationPage.qml qml/ReviewsPage.qml qml/AddonsView.qml qml/ApplicationDelegate.qml qml/InstallApplicationButton.qml qml/Rating.qml qml/UpdatesPage.qml qml/ReviewDialog.qml qml/ProgressView.qml qml/BrowsingPage.qml qml/InstalledPage.qml + qml/SearchPage.qml qml/Information.qml qml/SourcesPage.qml qml/ReviewDelegate.qml qml/Heading.qml qml/AddSourceDialog.qml qml/ConditionalLoader.qml qml/LinkButton.qml qml/ApplicationScreenshots.qml qml/LabelBackground.qml qml/PageHeader.qml qml/ActionBridge.qml qml/DiscoverSystemPalette.qml qml/DiscoverPage.qml qml/DiscoverWindow.qml qml/DiscoverDrawer.qml qml/ActionListItem.qml qml/LoadingPage.qml qml/navigation.js