diff --git a/discover/qml/ApplicationPage.qml b/discover/qml/ApplicationPage.qml index d2d49302..c9d91298 100644 --- a/discover/qml/ApplicationPage.qml +++ b/discover/qml/ApplicationPage.qml @@ -1,404 +1,367 @@ /* * 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.Controls 2.1 as QQC2 import QtQuick.Window 2.1 import QtQuick.Layouts 1.1 import org.kde.kquickcontrolsaddons 2.0 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import org.kde.kirigami 2.1 as Kirigami import "navigation.js" as Navigation DiscoverPage { id: appInfo property QtObject application: null clip: true title: application.name background: Rectangle { color: Kirigami.Theme.viewBackgroundColor } ReviewsPage { id: reviewsSheet model: ReviewsModel { id: reviewsModel resource: appInfo.application } } Kirigami.OverlaySheet { id: originsOverlay bottomPadding: Kirigami.Units.largeSpacing topPadding: Kirigami.Units.largeSpacing readonly property alias model: alternativeResourcesView.model function listBackends() { var first = true; var ret = ""; var m = alternativeResourcesView.model; for(var i=0, count=m.rowCount(); i" + res.displayOrigin + "" first = false } } return ret } readonly property string sentence: alternativeResourcesView.count <= 1 ? "" : i18n("\nAlso available in %1", listBackends()) ListView { id: alternativeResourcesView model: ResourcesProxyModel { allBackends: true resourcesUrl: appInfo.application.url } delegate: Kirigami.BasicListItem { label: displayOrigin checked: appInfo.application == model.application onClicked: if(index>=0) { var res = model.application console.assert(res) window.stack.pop() Navigation.openApplication(res) } } } } - header: QQC2.ToolBar { - anchors { - right: parent.right - left: parent.left + actions { + main: appbutton.action + right: Kirigami.Action { + visible: application.isInstalled && application.canExecute + text: application.executeLabel + icon.name: "media-playback-start" + onTriggered: application.invokeApplication() } + } - contentItem: RowLayout { - spacing: Kirigami.Units.smallSpacing - - ToolButton { - Layout.leftMargin: Kirigami.Units.smallSpacing - iconName: "draw-arrow-back" - tooltip: i18n("Back") - enabled: appInfo.sClose.enabled - onClicked: appInfo.sClose.activated() - } - Item { - Layout.fillWidth: true - } - Kirigami.Heading { - level: 3 - Layout.maximumWidth: parent.width/2 - text: appInfo.application.name - maximumLineCount: 1 - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - } - Item { - Layout.fillWidth: true - } - - Binding { - target: appInfo.actions - property: "main" - value: appbutton.action - } - - InstallApplicationButton { - id: appbutton - Layout.rightMargin: Kirigami.Units.smallSpacing - application: appInfo.application - visible: applicationWindow().wideScreen - } - - Button { - Layout.rightMargin: Kirigami.Units.smallSpacing - visible: application.isInstalled && application.canExecute - text: application.executeLabel - onClicked: application.invokeApplication() - } - } + InstallApplicationButton { + id: appbutton + Layout.rightMargin: Kirigami.Units.smallSpacing + application: appInfo.application + visible: false } leftPadding: Kirigami.Units.largeSpacing * (applicationWindow().wideScreen ? 2 : 1) rightPadding: Kirigami.Units.largeSpacing * (applicationWindow().wideScreen ? 2 : 1) // Icon, name, caption, screenshots, description and reviews ColumnLayout { spacing: 0 RowLayout { Kirigami.Icon { - Layout.topMargin: Kirigami.Units.smallSpacing * 2 Layout.preferredHeight: 80 Layout.preferredWidth: 80 source: appInfo.application.icon Layout.rightMargin: Kirigami.Units.smallSpacing * 2 } ColumnLayout { spacing: 0 Kirigami.Heading { level: 1 text: appInfo.application.name lineHeight: 1.0 maximumLineCount: 1 elide: Text.ElideRight Layout.fillWidth: true Layout.alignment: Text.AlignBottom } Kirigami.Heading { level: 4 text: appInfo.application.comment maximumLineCount: 2 lineHeight: lineCount > 1 ? 0.75 : 1.2 elide: Text.ElideRight Layout.fillWidth: true Layout.alignment: Qt.AlignTop } } Layout.bottomMargin: Kirigami.Units.largeSpacing } ApplicationScreenshots { id: screenshots Layout.fillWidth: true visible: count > 0 resource: appInfo.application QQC2.ScrollBar.horizontal: screenshotsScrollbar } QQC2.ScrollBar { id: screenshotsScrollbar Layout.fillWidth: true } QQC2.Label { Layout.topMargin: Kirigami.Units.largeSpacing Layout.fillWidth: true wrapMode: Text.WordWrap text: appInfo.application.longDescription + originsOverlay.sentence onLinkActivated: { var idx = parseInt(link, 10) var res = originsOverlay.model.resourceAt(idx) window.stack.pop() Navigation.openApplication(res) } } LinkButton { id: addonsButton text: i18n("Addons") visible: addonsView.containsAddons onClicked: addonsView.sheetOpen = true } Kirigami.Heading { Layout.topMargin: Kirigami.Units.largeSpacing text: i18n("Reviews") level: 2 visible: rep.count > 0 } Rectangle { color: Kirigami.Theme.linkColor Layout.fillWidth: true height: 1 visible: rep.count > 0 } Repeater { id: rep model: PaginateModel { sourceModel: reviewsSheet.model pageSize: 3 } delegate: ReviewDelegate { Layout.topMargin: Kirigami.Units.largeSpacing separator: false compact: true Layout.bottomMargin: Kirigami.Units.largeSpacing } } LinkButton { text: i18n("Be the first to write a review!") onClicked: reviewsSheet.openReviewDialog() visible: !commentsButton.visible && reviewsModel.backend && reviewsModel.backend.isResourceSupported(appInfo.application) } LinkButton { id: commentsButton readonly property QtObject rating: appInfo.application.rating visible: rating && rating.ratingCount>0 && reviewsModel.count text: i18n("Show more reviews (%1)...", rating ? reviewsModel.count : 0) onClicked: { reviewsSheet.open() } Layout.bottomMargin: Kirigami.Units.largeSpacing } Rectangle { color: Kirigami.Theme.linkColor Layout.fillWidth: true height: 1 Layout.bottomMargin: Kirigami.Units.largeSpacing } GridLayout { rowSpacing: 0 columns: 2 // Category row QQC2.Label { Layout.alignment: Qt.AlignRight text: i18n("Category:") } QQC2.Label { Layout.fillWidth: true elide: Text.ElideRight text: appInfo.application.categoryDisplay } // Version row QQC2.Label { visible: versionLabel.visible Layout.alignment: Qt.AlignRight text: i18n("Version:") } QQC2.Label { readonly property string version: appInfo.application.isInstalled ? appInfo.application.installedVersion : appInfo.application.availableVersion id: versionLabel visible: text.length > 0 Layout.fillWidth: true elide: Text.ElideRight text: version ? version : "" } // Size row QQC2.Label { Layout.alignment: Qt.AlignRight text: i18n("Size:") } QQC2.Label { Layout.fillWidth: true elide: Text.ElideRight text: i18n("%1", appInfo.application.sizeDescription) } // Source row QQC2.Label { Layout.alignment: Qt.AlignRight text: i18n("Source:") } LinkButton { Layout.fillWidth: true horizontalAlignment: Text.AlignLeft enabled: alternativeResourcesView.count > 1 text: appInfo.application.displayOrigin elide: Text.ElideRight onClicked: originsOverlay.open() } // License row QQC2.Label { Layout.alignment: Qt.AlignRight text: i18n("License:") visible: appInfo.application.license.length>0 } LinkButton { elide: Text.ElideRight Layout.fillWidth: true horizontalAlignment: Text.AlignLeft visible: text.length>0 text: appInfo.application.license // tooltip: i18n("See full license terms") onClicked: Qt.openUrlExternally("https://spdx.org/licenses/" + appInfo.application.license + ".html#licenseText") } // Homepage row QQC2.Label { visible: homepageLink.visible Layout.alignment: Qt.AlignRight text: i18n("Homepage:") } LinkButton { id: homepageLink visible: text.length > 0 text: application.homepage onClicked: Qt.openUrlExternally(application.homepage) elide: Text.ElideRight Layout.fillWidth: true horizontalAlignment: Text.AlignLeft } // "User Guide" row QQC2.Label { visible: docsLink.visible Layout.alignment: Qt.AlignRight text: i18n("User Guide:") } LinkButton { id: docsLink visible: text.length > 0 text: application.helpURL onClicked: Qt.openUrlExternally(helpURL) elide: Text.ElideRight Layout.fillWidth: true horizontalAlignment: Text.AlignLeft } // Donate row QQC2.Label { visible: donationLink.visible Layout.alignment: Qt.AlignRight text: i18n("Donate:") } LinkButton { id: donationLink visible: text.length > 0 text: application.donationURL onClicked: Qt.openUrlExternally(donationURL) elide: Text.ElideRight Layout.fillWidth: true horizontalAlignment: Text.AlignLeft } // "Report a Droblem" row QQC2.Label { visible: bugLink.visible Layout.alignment: Qt.AlignRight text: i18n("Report a Problem:") } LinkButton { id: bugLink visible: text.length > 0 text: application.bugURL onClicked: Qt.openUrlExternally(bugURL) elide: Text.ElideRight Layout.fillWidth: true horizontalAlignment: Text.AlignLeft } } } readonly property var addons: AddonsView { id: addonsView application: appInfo.application parent: overlay } } diff --git a/discover/qml/ApplicationsListPage.qml b/discover/qml/ApplicationsListPage.qml index ac4c96cf..b584dad1 100644 --- a/discover/qml/ApplicationsListPage.qml +++ b/discover/qml/ApplicationsListPage.qml @@ -1,167 +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.Controls 2.1 as QQC2 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 extending: appsModel.extending 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 alias listHeaderPositioning: apps.headerPositioning property bool compact: page.width < 500 || !applicationWindow().wideScreen property bool canNavigate: true readonly property alias subcategories: appsModel.subcategories title: category ? category.name : "" onSearchChanged: { appsModel.sortOrder = Qt.AscendingOrder } signal clearSearch() supportsRefreshing: true onRefreshingChanged: if (refreshing) { appsModel.invalidateFilter() refreshing = false } ListView { id: apps section.delegate: QQC2.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 onBusyChanged: if (isBusy) { apps.currentIndex = -1 } } 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 } QQC2.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; } } } ] QQC2.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/BrowsingPage.qml b/discover/qml/BrowsingPage.qml index a0d33a01..a1a561a9 100644 --- a/discover/qml/BrowsingPage.qml +++ b/discover/qml/BrowsingPage.qml @@ -1,69 +1,64 @@ /* * Copyright (C) 2015 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.4 import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 import org.kde.discover 2.0 import org.kde.kquickcontrolsaddons 2.0 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import "navigation.js" as Navigation import org.kde.kirigami 2.1 as Kirigami DiscoverPage { id: page title: i18n("Featured") leftPadding: 0 rightPadding: 0 topPadding: 0 bottomPadding: 0 readonly property bool isHome: true function searchFor(text) { if (text.length === 0) return; Navigation.openCategory(null, "") } signal clearSearch() readonly property bool compact: page.width < 500 || !applicationWindow().wideScreen ListView { id: browsingView - headerPositioning: ListView.OverlayHeader - header: Kirigami.ItemViewHeader { - backgroundImage.source: "qrc:/banners/coffee.jpg" - title: page.title - } model: FeaturedModel {} 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 } } } diff --git a/discover/qml/DiscoverWindow.qml b/discover/qml/DiscoverWindow.qml index 11052dd2..eb526121 100644 --- a/discover/qml/DiscoverWindow.qml +++ b/discover/qml/DiscoverWindow.qml @@ -1,209 +1,214 @@ import QtQuick 2.5 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.1 import QtQuick.Controls 2.1 as QQC2 import org.kde.discover 2.0 import org.kde.discover.app 1.0 -import org.kde.kirigami 2.0 as Kirigami +import org.kde.kirigami 2.2 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 + header: Kirigami.ToolBarApplicationHeader {} +// header: (window.wideScreen ? desktopHeader : mobileHeader).createObject() +// +// Component { id: desktopHeader; Kirigami.ToolBarApplicationHeader {} } +// Component { id: mobileHeader; Kirigami.ApplicationHeader {} } + 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" } 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" } TopLevelPageData { id: updateAction iconName: ResourcesModel.updatesCount>0 ? ResourcesModel.hasSecurityUpdates ? "update-high" : "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" } TopLevelPageData { id: settingsAction iconName: "settings" text: i18n("Settings") component: topSourcesComp objectName: "settings" } Action { id: refreshAction readonly property QtObject action: ResourcesModel.updateAction text: action.text onTriggered: action.trigger() enabled: action.enabled tooltip: shortcut shortcut: "Ctrl+R" } Connections { target: app onOpenApplicationInternal: { Navigation.clearStack() Navigation.openApplication(app) } onListMimeInternal: { currentTopLevel = topBrowsingComp; Navigation.openApplicationMime(mime) } onListCategoryInternal: { currentTopLevel = topBrowsingComp; Navigation.openCategory(cat, "") } onOpenSearch: { Navigation.clearStack() Navigation.openApplicationList({search: search}) } onPreventedClose: showPassiveNotification(i18n("Could not close the application, there are tasks that need to be done.")) onUnableToFind: { showPassiveNotification(i18n("Unable to find resource: %1", resid)); Navigation.openHome() } } Connections { target: ResourcesModel onPassiveMessage: { showPassiveNotification(message) 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 } QQC2.Label { id: desc Layout.fillWidth: true textFormat: Text.StyledText wrapMode: Text.WordWrap } RowLayout { Layout.alignment: Qt.AlignRight Button { text: i18n("Proceed") iconName: "dialog-ok" onClicked: { transaction.proceed() sheet.acted = true sheet.close() } } Button { Layout.alignment: Qt.AlignRight text: i18n("Cancel") iconName: "dialog-cancel" onClicked: { transaction.cancel() 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 } 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/InstallApplicationButton.qml b/discover/qml/InstallApplicationButton.qml index aff414c3..22c1d78a 100644 --- a/discover/qml/InstallApplicationButton.qml +++ b/discover/qml/InstallApplicationButton.qml @@ -1,80 +1,80 @@ import QtQuick 2.1 import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 import org.kde.discover 2.0 import org.kde.kirigami 2.0 as Kirigami ConditionalLoader { id: root property alias application: listener.resource readonly property alias isActive: listener.isActive readonly property alias progress: listener.progress readonly property alias listener: listener readonly property string text: !application.isInstalled ? i18n("Install") : i18n("Remove") property Component additionalItem: null property bool flat: false TransactionListener { id: listener } property QtObject action: Kirigami.Action { text: root.text icon { name: application.isInstalled ? "trash-empty" : "cloud-download" color: application.isInstalled ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.positiveTextColor } - visible: !listener.isActive && !applicationWindow().wideScreen + visible: !listener.isActive onTriggered: root.click() } function click() { if (!isActive) { if(application.isInstalled) ResourcesModel.removeApplication(application); else ResourcesModel.installApplication(application); } else { console.warn("trying to un/install but resouce still active", application.name) } } condition: listener.isActive componentTrue: RowLayout { LabelBackground { Layout.fillWidth: true text: listener.statusText progress: listener.progress/100 } ToolButton { Layout.fillHeight: true iconName: "dialog-cancel" enabled: listener.isCancellable onClicked: listener.cancel() } } Component { id: flatButton ToolButton { enabled: application.state != AbstractResource.Broken text: root.text onClicked: root.click() } } Component { id: fullButton Button { enabled: application.state != AbstractResource.Broken text: root.text onClicked: root.click() } } componentFalse: root.flat ? flatButton : fullButton } diff --git a/discover/qml/InstalledPage.qml b/discover/qml/InstalledPage.qml index 6ad54808..cf360558 100644 --- a/discover/qml/InstalledPage.qml +++ b/discover/qml/InstalledPage.qml @@ -1,29 +1,20 @@ import QtQuick 2.1 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.1 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import org.kde.kirigami 2.1 as Kirigami ApplicationsListPage { id: page stateFilter: AbstractResource.Installed sortRole: ResourcesProxyModel.NameRole sortOrder: Qt.AscendingOrder allBackends: true title: i18n("Installed") compact: true canNavigate: false listHeader: null - header: ToolBar { - Kirigami.Heading { - anchors { - right: parent.right - rightMargin: Kirigami.Units.largeSpacing - } - text: page.title - } - } } diff --git a/discover/qml/SearchPage.qml b/discover/qml/KirigamiActionBridge.qml similarity index 67% copy from discover/qml/SearchPage.qml copy to discover/qml/KirigamiActionBridge.qml index ea066624..9aa542f2 100644 --- a/discover/qml/SearchPage.qml +++ b/discover/qml/KirigamiActionBridge.qml @@ -1,52 +1,39 @@ /*************************************************************************** - * Copyright © 2017 Aleix Pol Gonzalez * + * 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 QtQml 2.0 +import org.kde.kirigami 2.1 as Kirigami -ApplicationsListPage { - id: searchPage +Kirigami.Action +{ + property QtObject action: null - signal shown() - Timer { - interval: 0 - running: true - onTriggered: { - searchPage.shown() - } + function removeAmpersand(text) { + return text.replace("&", ""); } + text: action ? removeAmpersand(action.text) : "" + checked: action && action.checked + enabled: action && action.enabled + tooltip: action ? action.toolTip : "" + iconName: action ? app.iconName(action.icon) : "" + shortcut: action ? action.shortcut : undefined - listHeaderExtra: SearchField { - id: searchField - focus: true - Component.onCompleted: forceActiveFocus() - - Connections { - ignoreUnknownSignals: true - target: searchPage - onShown: { - searchField.forceActiveFocus() - } - } - - onCurrentSearchTextChanged: { - searchPage.search = currentSearchText - } - } + onTriggered: action.trigger() } diff --git a/discover/qml/SearchPage.qml b/discover/qml/SearchPage.qml index ea066624..ad4fe449 100644 --- a/discover/qml/SearchPage.qml +++ b/discover/qml/SearchPage.qml @@ -1,52 +1,55 @@ /*************************************************************************** * 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 QtQuick 2.5 ApplicationsListPage { id: searchPage signal shown() Timer { interval: 0 running: true onTriggered: { searchPage.shown() } } - listHeaderExtra: SearchField { + listHeaderPositioning: ListView.OverlayHeader + listHeader: SearchField { id: searchField + width: parent.width focus: true + z: 100 Component.onCompleted: forceActiveFocus() Connections { ignoreUnknownSignals: true target: searchPage onShown: { searchField.forceActiveFocus() } } onCurrentSearchTextChanged: { searchPage.search = currentSearchText } } } diff --git a/discover/qml/SourcesPage.qml b/discover/qml/SourcesPage.qml index 14146a63..ffbcfc28 100644 --- a/discover/qml/SourcesPage.qml +++ b/discover/qml/SourcesPage.qml @@ -1,234 +1,207 @@ import QtQuick 2.4 import QtQuick.Controls 1.1 import QtQuick.Controls 2.1 as QQC2 import QtQuick.Layouts 1.1 import org.kde.discover 2.0 import org.kde.discover.app 1.0 import org.kde.kquickcontrolsaddons 2.0 import org.kde.kirigami 2.2 as Kirigami import "navigation.js" as Navigation DiscoverPage { id: page clip: true title: i18n("Settings") property string search: "" Kirigami.Theme.inherit: false Kirigami.Theme.colorSet: Kirigami.Theme.View background: Rectangle { color: Kirigami.Theme.backgroundColor } - header: QQC2.ToolBar { - Kirigami.Theme.inherit: false - Kirigami.Theme.colorSet: Kirigami.Theme.Window - anchors { - right: parent.right - left: parent.left - } - - contentItem: RowLayout { - anchors { - topMargin: Kirigami.Units.smallSpacing - bottomMargin: Kirigami.Units.smallSpacing - } - - Item { - Layout.fillWidth: true - } - - ToolButton { - action: refreshAction - } - - ToolButton { - text: i18n("Help...") - menu: Menu { - MenuItem { action: ActionBridge { action: app.action("help_contents") } } - MenuItem { action: ActionBridge { action: app.action("help_about_app") } } - MenuItem { action: ActionBridge { action: app.action("help_report_bug") } } - } - } - } - } + contextualActions: [ + KirigamiActionBridge { action: app.action("help_contents") }, + KirigamiActionBridge { action: app.action("help_about_app") }, + KirigamiActionBridge { action: app.action("help_report_bug") } + ] mainItem: ListView { id: sourcesView model: QSortFilterProxyModel { filterRegExp: new RegExp(page.search, 'i') sortRole: SourcesModelClass.SourceNameRole sourceModel: SourcesModel } currentIndex: -1 Component { id: sourceBackendDelegate Kirigami.AbstractListItem { id: backendItem hoverEnabled: false supportsMouseEvents: false readonly property QtObject backend: sourcesBackend readonly property bool isDefault: ResourcesModel.currentApplicationBackend == resourcesBackend RowLayout { Connections { target: backendItem.backend onPassiveMessage: window.showPassiveNotification(message) } anchors { right: parent.right left: parent.left rightMargin: parent.rightPadding leftMargin: parent.leftPadding } Kirigami.Heading { Layout.fillWidth: true text: backendItem.isDefault ? i18n("%1 (Default)", resourcesBackend.displayName) : resourcesBackend.displayName } Button { Layout.rightMargin: Kirigami.Units.smallSpacing iconName: "preferences-other" visible: resourcesBackend && resourcesBackend.hasApplications Component { id: dialogComponent AddSourceDialog { source: backendItem.backend onVisibleChanged: if (!visible) { destroy() } } } menu: Menu { id: settingsMenu MenuItem { enabled: !backendItem.isDefault text: i18n("Make default") onTriggered: ResourcesModel.currentApplicationBackend = backendItem.backend.resourcesBackend } MenuItem { text: i18n("Add Source...") visible: backendItem.backend onTriggered: { var addSourceDialog = dialogComponent.createObject(null, {displayName: backendItem.backend.resourcesBackend.displayName }) addSourceDialog.open() } } MenuSeparator { visible: backendActionsInst.count>0 } Instantiator { id: backendActionsInst model: ActionsModel { actions: backendItem.backend ? backendItem.backend.actions : undefined } delegate: MenuItem { - action: ActionBridge { action: modelData } + action: ActionBridge { action: modelData.action } } onObjectAdded: { settingsMenu.insertItem(index, object) } onObjectRemoved: { object.destroy() } } } } } } } delegate: ConditionalLoader { anchors { right: parent.right left: parent.left } readonly property variant resourcesBackend: model.resourcesBackend readonly property variant sourcesBackend: model.sourcesBackend readonly property variant display: model.display readonly property variant checked: model.checked readonly property variant statusTip: model.statusTip readonly property variant toolTip: model.toolTip readonly property variant sourceId: model.sourceId readonly property variant modelIndex: sourcesView.model.index(index, 0) condition: resourcesBackend != null componentTrue: sourceBackendDelegate componentFalse: sourceDelegate } Component { id: sourceDelegate Kirigami.SwipeListItem { Layout.fillWidth: true enabled: display.length>0 highlighted: ListView.isCurrentItem onClicked: Navigation.openApplicationListSource(display) Keys.onReturnPressed: clicked() actions: [ Kirigami.Action { iconName: "edit-delete" tooltip: i18n("Delete the origin") onTriggered: { var backend = sourcesBackend if (!backend.removeSource(sourceId)) { window.showPassiveNotification(i18n("Failed to remove the source '%1'", display)) } } } ] RowLayout { CheckBox { id: enabledBox readonly property variant modelChecked: sourcesView.model.data(modelIndex, Qt.CheckStateRole) checked: modelChecked != Qt.Unchecked enabled: modelChecked !== undefined onClicked: { sourcesView.model.setData(modelIndex, checkedState, Qt.CheckStateRole) } } QQC2.Label { text: display + " - " + toolTip + "" elide: Text.ElideRight Layout.fillWidth: true } } } } footer: ColumnLayout { id: foot anchors { right: parent.right left: parent.left margins: Kirigami.Units.smallSpacing } Repeater { id: back model: ResourcesProxyModel { extending: "org.kde.discover.desktop" } delegate: RowLayout { visible: !model.application.isInstalled QQC2.Label { Layout.fillWidth: true text: name } InstallApplicationButton { application: application } } } } } } diff --git a/discover/resources.qrc b/discover/resources.qrc index 1e543b99..df8fbf6f 100644 --- a/discover/resources.qrc +++ b/discover/resources.qrc @@ -1,40 +1,41 @@ 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/AddSourceDialog.qml qml/ConditionalLoader.qml qml/LinkButton.qml qml/ApplicationScreenshots.qml qml/LabelBackground.qml qml/PageHeader.qml qml/ActionBridge.qml + qml/KirigamiActionBridge.qml qml/DiscoverSystemPalette.qml qml/DiscoverPage.qml qml/DiscoverWindow.qml qml/DiscoverDrawer.qml qml/ActionListItem.qml qml/LoadingPage.qml qml/SearchField.qml qml/Shadow.qml qml/navigation.js