/*Copyright (C) 2011 Martin GrΓ€Γlin <mgraesslin@kde.org>Copyright (C) 2012 Gregor Taetzner <gregor@freenet.de>Copyright 2014 Sebastian KΓΌgler <sebas@kde.org>Copyright (C) 2015-2018 Eike Hein <hein@kde.org>Copyright (C) 2021 by Mikel Johnson <mikel5764@gmail.com>This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.*/import QtQuick 2.0import org.kde.plasma.core 2.0 as PlasmaCoreimport org.kde.plasma.components 3.0 as PlasmaComponents3import org.kde.plasma.extras 2.0 as PlasmaExtrasFocusScope {id: appViewContainerproperty QtObject activatedSection: nullproperty string rootBreadcrumbName: ""signal appModelChange()onAppModelChange: {if (activatedSection != null) {applicationsView.clearBreadcrumbs();applicationsView.listView.model = activatedSection;}}objectName: "ApplicationsView"property ListView listView: applicationsView.listViewfunction keyNavUp() {return applicationsView.keyNavUp();}function keyNavDown() {return applicationsView.keyNavDown();}function activateCurrentIndex() {applicationsView.state = "OutgoingLeft";}function openContextMenu() {applicationsView.currentItem.openActionMenu();}function deactivateCurrentIndex() {if (crumbModel.count > 0) { // this is not the case when switching from the right sidebar to the left when going "left"breadcrumbsElement.children[crumbModel.count-1].clickCrumb();applicationsView.state = "OutgoingRight";return true;}return false;}function reset() {applicationsView.model = activatedSection;applicationsView.clearBreadcrumbs();if (applicationsView.model == null) {applicationsView.currentIndex = -1} else {applicationsView.currentIndex = 0}}function refreshed() {reset();updatedLabelTimer.running = true;}Connections {target: plasmoidfunction onExpandedChanged() {if (!plasmoid.expanded) {reset();}}}Connections {target: rootBreadcrumbfunction onRootClick() {applicationsView.newModel = activatedSection;}}Item {id: crumbContaineranchors {top: parent.topleft: parent.leftright: parent.right}visible: applicationsView.model != null && applicationsView.model.description && applicationsView.model.description != "KICKER_ALL_MODEL"height: visible ? breadcrumbFlickable.height : 0Behavior on opacity {NumberAnimation {duration: PlasmaCore.Units.longDurationeasing.type: Easing.InOutQuad}}PlasmaCore.SvgItem {id: horizontalSeparatoropacity: applicationsView.listView.contentY !== 0height: PlasmaCore.Units.devicePixelRatioelementId: "horizontal-line"z: 1anchors {left: parent.leftleftMargin: PlasmaCore.Units.smallSpacing * 4right: parent.rightrightMargin: PlasmaCore.Units.smallSpacing * 4bottom: parent.bottom}Behavior on opacity {NumberAnimation {duration: PlasmaCore.Units.shortDurationeasing.type: Easing.InOutQuad}}svg: PlasmaCore.Svg {imagePath: "widgets/line"}}Flickable {id: breadcrumbFlickableanchors {top: parent.topleft: parent.leftright: parent.right}height: breadcrumbsElement.heightboundsBehavior: Flickable.StopAtBoundscontentWidth: breadcrumbsElement.widthpixelAligned: true// HACK: Align the content to right for RTL localesleftMargin: LayoutMirroring.enabled ? Math.max(0, width - contentWidth) : 0Row {id: breadcrumbsElementspacing: PlasmaCore.Units.smallSpacing * 2Breadcrumb {id: rootBreadcrumbroot: truetext: rootBreadcrumbNamedepth: 0}Repeater {model: ListModel {id: crumbModel// Array of the modelsproperty var models: []}Breadcrumb {root: falsetext: model.text}}onWidthChanged: {if (LayoutMirroring.enabled) {breadcrumbFlickable.contentX = -Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)} else {breadcrumbFlickable.contentX = Math.max(0, breadcrumbsElement.width - breadcrumbFlickable.width)}}}} // Flickable} // crumbContainerKickoffListView {id: applicationsViewanchors {top: crumbContainer.bottombottom: parent.bottom}width: parent.widthproperty Item activatedItem: nullproperty var newModel: nullsection.property: model && model.description == "KICKER_ALL_MODEL" ? "display" : ""section.criteria: ViewSection.FirstCharacterBehavior on opacity {NumberAnimation {duration: PlasmaCore.Units.longDurationeasing.type: Easing.InOutQuad}}focus: trueappView: truefunction moveLeft() {state = "Normal";// newModelIndex set by clicked breadcrumbvar oldModel = applicationsView.model;applicationsView.model = applicationsView.newModel;var oldModelIndex = model.rowForModel(oldModel);// new model may not be a parent of old model (e.g. grandparent)if (oldModelIndex === -1) {listView.positionAtBeginning()} else {listView.currentIndex = oldModelIndex;listView.positionViewAtIndex(oldModelIndex, ListView.Center);}}function moveRight() {state = "Normal";activatedItem.activate()applicationsView.listView.positionAtBeginning()}function clearBreadcrumbs() {crumbModel.clear();crumbModel.models = [];}onReset: appViewContainer.reset()onAddBreadcrumb: {crumbModel.append({"text": title, "depth": crumbModel.count+1})crumbModel.models.push(model);}state: "Normal"states: [State {name: "Normal"PropertyChanges {target: applicationsViewx: 0opacity: 1.0}},State {name: "OutgoingLeft"PropertyChanges {target: applicationsViewx: LayoutMirroring.enabled ? parent.width : -parent.widthopacity: 0.0}},State {name: "OutgoingRight"PropertyChanges {target: applicationsViewx: LayoutMirroring.enabled ? -parent.width : parent.widthopacity: 0.0}}]transitions: [Transition {to: "OutgoingLeft"SequentialAnimation {// We need to cache the currentItem since the selection can move during animation,// and we want the item that has been clicked on, not the one that is under the// mouse once the animation is doneScriptAction {script: applicationsView.activatedItem = applicationsView.currentItem}NumberAnimation {properties: "x"easing.type: Easing.InQuadduration: PlasmaCore.Units.longDuration}ScriptAction {script: applicationsView.moveRight()}}},Transition {to: "OutgoingRight"SequentialAnimation {NumberAnimation {properties: "x"easing.type: Easing.InQuadduration: PlasmaCore.Units.longDuration}ScriptAction {script: applicationsView.moveLeft()}}}]}MouseArea {anchors.fill: parentacceptedButtons: Qt.BackButtononClicked: {deactivateCurrentIndex()}}// Displays text when application list gets updatedTimer {id: updatedLabelTimer// We want to have enough time to show that applications have been updated even for those who disabled animationsinterval: 1500running: falserepeat: trueonRunningChanged: {if (running) {updatedLabel.opacity = 1;crumbContainer.opacity = 0;applicationsView.listView.opacity = 0;}}onTriggered: {updatedLabel.opacity = 0;crumbContainer.opacity = 1;applicationsView.listView.opacity = 1;running = false;}}PlasmaExtras.PlaceholderMessage {id: updatedLabelwidth: parent.width - (PlasmaCore.Units.largeSpacing * 4)text: i18n("Updating applications...")iconName: "view-refresh"opacity: 0visible: opacity != 0anchors.centerIn: parentBehavior on opacity {NumberAnimation {duration: PlasmaCore.Units.shortDurationeasing.type: Easing.InOutQuad}}}Component.onCompleted: {rootModel.cleared.connect(refreshed);}} // appViewContainer