/*************************************************************************** * Copyright (C) 2013-2015 by Eike Hein * * Copyright (C) 2021 by Prateek SU * * * * 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) any later version. * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.kquickcontrolsaddons 2.0 as KQuickAddons import QtQuick 2.12 import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.components 2.0 as PlasmaComponents2 import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kwindowsystem 1.0 import org.kde.plasma.private.kicker 0.1 as Kicker import org.kde.kcoreaddons 1.0 as KCoreAddons import "../code/tools.js" as Tools Item { id: item width: cellSize * (plasmoid.configuration.numberColumns + 1.3) height: root.height y: units.largeSpacing * 2 property int iconSize: units.iconSizes.large property int cellSize: iconSize + theme.mSize(theme.defaultFont).height + (2 * units.smallSpacing) + (2 * Math.max(highlightItemSvg.margins.top + highlightItemSvg.margins.bottom, highlightItemSvg.margins.left + highlightItemSvg.margins.right)) property bool searching: (searchField.text != "") property bool showAllApps: plasmoid.configuration.defaultAllApps property bool showRecents: false property int tileSide: cellSize * 1.08 onSearchingChanged: { if (!searching) { reset(); } else { if (showRecents) resetPinned.start(); } } signal newTextQuery(string text) property real mainColumnHeight: tileSide * plasmoid.configuration.numberRows property real favoritesColumnHeight: tileSide * 0.6 * 3 property var pinnedModel: [globalFavorites, rootModel.modelForRow(0), rootModel.modelForRow(1)] property var recommendedModel: [rootModel.modelForRow(1), rootModel.modelForRow(0), globalFavorites, globalFavorites] property var allAppsModel: [rootModel.modelForRow(2)] function updateModels() { item.pinnedModel = [globalFavorites, rootModel.modelForRow(0), rootModel.modelForRow(1)] item.recommendedModel = [rootModel.modelForRow(1), rootModel.modelForRow(0), globalFavorites, globalFavorites] item.allAppsModel = [rootModel.modelForRow(2)] } function reset() { if (showRecents) resetPinned.start(); searchField.clear() searchField.focus = true showAllApps = plasmoid.configuration.defaultAllApps showRecents = false documentsFavoritesGrid.tryActivate(0, 0); allAppsGrid.tryActivate(0, 0); globalFavoritesGrid.tryActivate(0, 0); } function reload() { mainColumn.visible = false recentItem.visible = false pinnedModel = null recommendedModel = null allAppsModel = null preloadAllAppsTime.done = false preloadAllAppsTime.defer() } KWindowSystem { id: kwindowsystem } KCoreAddons.KUser { id: kuser } PlasmaExtras.Heading { id: dummyHeading visible: false width: 0 level: 1 } ParallelAnimation { id: removePinned running: false NumberAnimation { target: mainColumn; property: "height"; from: mainColumnHeight; to: 0; duration: 500; easing.type: Easing.InOutQuad } NumberAnimation { target: mainColumn; property: "opacity"; from: 1; to: 0; duration: 500; easing.type: Easing.InOutQuad } NumberAnimation { target: documentsFavoritesGrid; property: "height"; from: favoritesColumnHeight; to: parent.height; duration: 500; easing.type: Easing.InOutQuad } } ParallelAnimation { id: restorePinned running: false NumberAnimation { target: mainColumn; property: "height"; from: 0; to: searching || showAllApps ? parent.height : mainColumnHeight; duration: 500; easing.type: Easing.InOutQuad } NumberAnimation { target: mainColumn; property: "opacity"; from: 0; to: 1; duration: 500; easing.type: Easing.InOutQuad } NumberAnimation { target: documentsFavoritesGrid; property: "height"; from: parent.height; to: favoritesColumnHeight; duration: 500; easing.type: Easing.InOutQuad } } ParallelAnimation { id: resetPinned running: false NumberAnimation { target: mainColumn; property: "height"; from: 0; to: searching || showAllApps ? parent.height : mainColumnHeight; duration: 0; } NumberAnimation { target: mainColumn; property: "opacity"; from: 0; to: 1; duration: 0; } NumberAnimation { target: documentsFavoritesGrid; property: "height"; from: parent.height; to: favoritesColumnHeight; duration: 0; } } TextMetrics { id: headingMetrics font: dummyHeading.font } Timer { id: preloadAllAppsTime property bool done: false interval: 100 repeat: false onTriggered: { if (done) { return; } item.updateModels() mainColumn.tryActivate(0, 0); done = true; mainColumn.visible = true recentItem.visible = true } function defer() { if (!running && !done) { restart(); } } } Kicker.ContainmentInterface { id: containmentInterface } PlasmaComponents2.Menu { id: contextMenu PlasmaComponents2.MenuItem { action: plasmoid.action("configure") } } PlasmaComponents.TextField { id: searchField focus: true placeholderText: i18n("Type here to search") opacity: searching || plasmoid.configuration.alwaysShowSearchBar leftPadding: PlasmaCore.Units.iconSizes.small * 1.9 height: units.iconSizes.medium width: parent.width - 2 * x x: 1.5 * units.largeSpacing Accessible.editable: true Accessible.searchEdit: true onTextChanged: { runnerModel.query = text; newTextQuery(text) } PlasmaCore.IconItem { id: searchIconItem source: "search" height: PlasmaCore.Units.iconSizes.small width: height x: PlasmaCore.Units.iconSizes.small * 0.45 anchors { verticalCenter: searchField.verticalCenter } } function clear() { text = ""; } function backspace() { if (searching) { text = text.slice(0, -1); } focus = true; } function appendText(newText) { if (!root.visible) { return; } focus = true; text = text + newText; } Keys.onPressed: { if (event.key == Qt.Key_Down) { event.accepted = true; mainColumn.tryActivate(0, 0) } else if (event.key == Qt.Key_Tab || event.key == Qt.Key_Up) { event.accepted = true; mainColumn.tryActivate(0, 0) } else if (event.key == Qt.Key_Escape) { event.accepted = true; if (searching) { clear() } else { root.toggle() } } } } PlasmaExtras.Heading { id: mainLabelGrid anchors.top: plasmoid.configuration.alwaysShowSearchBar ? searchField.bottom : parent.top anchors.leftMargin: units.largeSpacing * 3 anchors.topMargin: plasmoid.configuration.alwaysShowSearchBar ? units.largeSpacing : 0 anchors.left: parent.left x: units.smallSpacing elide: Text.ElideRight wrapMode: Text.NoWrap color: theme.textColor level: 5 font.bold: true font.weight: Font.Bold text: showAllApps ? i18n("All apps") : showRecents ? i18n("Recommended") : i18n("Pinned") visible: !searching } PlasmaComponents.Button { MouseArea { hoverEnabled: true anchors.fill: parent cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor onClicked: { if (showAllApps || !showRecents) showAllApps = !showAllApps else { showRecents = !showRecents if (showRecents) removePinned.start(); else restorePinned.start(); } mainColumn.visibleGrid.tryActivate(0, 0) } } text: i18n(showAllApps || showRecents ? "Back" : "All apps") id: mainsecLabelGrid icon.name: showAllApps || showRecents ? "go-previous" : "go-next" font.pointSize: 9 icon.height: 15 icon.width: icon.height LayoutMirroring.enabled: true LayoutMirroring.childrenInherit: !showAllApps && !showRecents flat: false background: Rectangle { color: Qt.lighter(theme.backgroundColor) border.width: 1 border.color: Qt.darker(theme.backgroundColor, 1.14) radius: 5 } topPadding: 4 bottomPadding: topPadding leftPadding: 8 rightPadding: 8 icon{ width: height height: visible ? units.iconSizes.small : 0 name: showAllApps || showRecents ? "go-previous" : "go-next" } anchors { topMargin: units.smallSpacing verticalCenter: mainLabelGrid.verticalCenter rightMargin: units.largeSpacing * 3 leftMargin: units.largeSpacing * 3 left: parent.left } x: -units.smallSpacing visible: !searching } Item { id: mainColumn anchors { top: searching ? searchField.bottom : mainLabelGrid.bottom leftMargin: units.largeSpacing * 1.6 rightMargin: units.largeSpacing topMargin: units.largeSpacing * 0.7 left: parent.left right: parent.right bottom: searching ? parent.bottom : showAllApps ? footer.top : undefined bottomMargin: showAllApps ? 5 : 0 } height: searching || showAllApps || plasmoid.configuration.recentGridModel == 3 ? parent.height : mainColumnHeight property Item visibleGrid: globalFavoritesGrid function tryActivate(row, col) { if (visibleGrid) { visibleGrid.tryActivate(row, col); } } ItemGridView { id: globalFavoritesGrid model: pinnedModel[plasmoid.configuration.favGridModel] width: parent.width height: plasmoid.configuration.recentGridModel == 3 ? parent.height : mainColumnHeight cellWidth: tileSide cellHeight: tileSide square: true dropEnabled: true usesPlasmaTheme: true z: (opacity == 1.0) ? 1 : 0 enabled: (opacity == 1.0) ? 1 : 0 verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff opacity: searching || showAllApps ? 0 : 1 onOpacityChanged: { if (opacity == 1.0) { mainColumn.visibleGrid = globalFavoritesGrid; } } onKeyNavDown: documentsFavoritesGrid.tryActivate(0, 0) } ItemMultiGridView { id: allAppsGrid anchors.fill: parent z: (opacity == 1.0) ? 1 : 0 enabled: (opacity == 1.0) ? 1 : 0 height: parent.height width: parent.width grabFocus: true model: allAppsModel[0] opacity: showAllApps && !searching ? 1.0 : 0.0 showDescriptions: plasmoid.configuration.showDescription anchors { leftMargin: units.largeSpacing * 1.6; } onOpacityChanged: { if (opacity == 1.0) { mainColumn.visibleGrid = allAppsGrid; } } } ItemMultiGridView { id: runnerGrid anchors.fill: parent z: (opacity == 1.0) ? 1 : 0 enabled: (opacity == 1.0) ? 1 : 0 width: parent.width model: runnerModel showDescriptions: plasmoid.configuration.showDescription grabFocus: true opacity: searching ? 1.0 : 0.0 onOpacityChanged: { if (opacity == 1.0) { mainColumn.visibleGrid = runnerGrid; } } } Keys.onPressed: { if (event.key == Qt.Key_Backspace) { event.accepted = true; if (searching) searchField.backspace(); else searchField.focus = true } else if (event.key == Qt.Key_Tab) { event.accepted = true; if (!searching && !showAllApps) documentsFavoritesGrid.tryActivate(0, 0); } else if (event.key == Qt.Key_Escape) { event.accepted = true; if (searching) { searchField.clear() } else { root.toggle() } } else if (event.text != "") { event.accepted = true; searchField.appendText(event.text); } } MouseArea { anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton LayoutMirroring.enabled: Qt.application.layoutDirection == Qt.RightToLeft LayoutMirroring.childrenInherit: true onPressed: { if (mouse.button == Qt.RightButton) { contextMenu.open(mouse.x, mouse.y); } } onClicked: { if (mouse.button == Qt.LeftButton) { } } } } Item{ id: recentItem width: parent.width anchors.top: mainColumn.bottom anchors.topMargin: units.largeSpacing * 0.5 anchors.left: parent.left anchors.bottom: parent.bottom anchors.leftMargin: units.largeSpacing * 3 anchors.rightMargin: units.largeSpacing visible: plasmoid.configuration.recentGridModel != 3 property int iconSize: 22 PlasmaExtras.Heading { id: headLabelDocuments x: units.smallSpacing width: parent.width - x elide: Text.ElideRight wrapMode: Text.NoWrap color: theme.textColor level: 5 font.bold: true font.weight: Font.Bold visible: !searching && !showAllApps && !showRecents text: i18n("Recommended") } PlasmaComponents.Button { MouseArea { hoverEnabled: true anchors.fill: parent cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor onClicked: { showRecents = !showRecents if (showRecents) removePinned.start(); else restorePinned.start(); } } text: i18n(showRecents ? "Back" : "More") id: headsecLabelGrid icon.name: showRecents ? "go-previous" : "go-next" font.pointSize: 9 icon.height: 15 icon.width: icon.height LayoutMirroring.enabled: true LayoutMirroring.childrenInherit: !showRecents flat: false background: Rectangle { color: Qt.lighter(theme.backgroundColor) border.width: 1 border.color: Qt.darker(theme.backgroundColor, 1.14) radius: 5 } topPadding: 4 bottomPadding: topPadding leftPadding: 8 rightPadding: 8 icon{ width: height height: visible ? units.iconSizes.small : 0 name: showRecents ? "go-previous" : "go-next" } anchors { verticalCenter: headLabelDocuments.verticalCenter rightMargin: units.largeSpacing * 6 leftMargin: units.largeSpacing * 6 left: parent.left } x: -units.smallSpacing visible: documentsFavoritesGrid.model != null && documentsFavoritesGrid.model.count > 6 && !searching && !showAllApps && !showRecents } ItemGridView { id: documentsFavoritesGrid visible: !searching && !showAllApps showDescriptions: true anchors{ top: headLabelDocuments.bottom left: parent.left right: parent.right bottomMargin: 0 topMargin: units.largeSpacing * 0.7 } increaseLeftSpacings: true height: showRecents ? parent.height : favoritesColumnHeight cellWidth: parent.width * 0.4 cellHeight: tileSide * 0.6 iconSize: units.iconSizes.medium model: recommendedModel[plasmoid.configuration.recentGridModel] usesPlasmaTheme: false onKeyNavUp: { mainColumn.visibleGrid.tryActivate(0, 0); } Keys.onPressed: { if (event.key == Qt.Key_Tab) { event.accepted = true; mainColumn.visibleGrid.tryActivate(0, 0) } else if (event.key == Qt.Key_Backspace) { event.accepted = true; if (searching) searchField.backspace(); else searchField.focus = true } else if (event.key == Qt.Key_Escape) { event.accepted = true; if (searching) { searchField.clear() } else { root.toggle() } } else if (event.text != "") { event.accepted = true; searchField.appendText(event.text); } } } } Footer { id: footer visible: !searching anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom } Component.onCompleted: { searchField.focus = true } }