/* * Copyright 2019 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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.12 import QtQuick.Window 2.12 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.draganddrop 2.0 as DragDrop import "launcher" as Launcher import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager import org.kde.phone.homescreen 1.0 import org.kde.plasma.private.mobileshell 1.0 as MobileShell Item { id: root width: 640 height: 480 property Item toolBox //BEGIN functions //Autoscroll related functions function scrollLeft() { if (mainFlickable.atXBeginning) { return; } autoScrollTimer.scrollRight = false; autoScrollTimer.running = true; scrollLeftIndicator.opacity = 1; scrollRightIndicator.opacity = 0; } function scrollRight() { if (mainFlickable.atXEnd) { return; } autoScrollTimer.scrollRight = true; autoScrollTimer.running = true; scrollLeftIndicator.opacity = 0; scrollRightIndicator.opacity = 1; } function stopScroll() { autoScrollTimer.running = false; scrollLeftIndicator.opacity = 0; scrollRightIndicator.opacity = 0; } function recalculateMaxFavoriteCount() { if (!componentComplete) { return; } plasmoid.nativeInterface.applicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / appletsLayout.cellWidth)); } //END functions property bool componentComplete: false onWidthChanged: recalculateMaxFavoriteCount() onHeightChanged:recalculateMaxFavoriteCount() Component.onCompleted: { if (plasmoid.screen == 0) { MobileShell.HomeScreenControls.homeScreen = root MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window } componentComplete = true; recalculateMaxFavoriteCount() } Plasmoid.onScreenChanged: { if (plasmoid.screen == 0) { MobileShell.HomeScreenControls.homeScreen = root MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window } } Window.onWindowChanged: { if (plasmoid.screen == 0) { MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window } } Connections { property real lastRequestedPosition: 0 target: MobileShell.HomeScreenControls function onResetHomeScreenPosition() { scrollAnim.to = 0; scrollAnim.restart(); appDrawer.close(); } function onSnapHomeScreenPosition() { if (lastRequestedPosition > 0) { appDrawer.open(); } else { appDrawer.close(); } } function onRequestHomeScreenPosition(y) { appDrawer.offset += y; lastRequestedPosition = y; } } Timer { id: autoScrollTimer property bool scrollRight: true repeat: true interval: 1500 onTriggered: { scrollAnim.to = scrollRight ? //Scroll Right Math.min(mainFlickable.contentItem.width - mainFlickable.width, mainFlickable.contentX + mainFlickable.width) : //Scroll Left Math.max(0, mainFlickable.contentX - mainFlickable.width); scrollAnim.running = true; } } Connections { target: plasmoid onEditModeChanged: { appletsLayout.editMode = plasmoid.editMode } } Launcher.LauncherDragManager { id: launcherDragManager anchors.fill: parent z: 2 appletsLayout: appletsLayout favoriteStrip: favoriteStrip } //TODO: this flickable does nothing for now, will be used for horizontal paging Flickable { id: mainFlickable anchors { fill: parent topMargin: plasmoid.availableScreenRect.y bottomMargin: favoriteStrip.height + plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y } opacity: 1 - appDrawer.openFactor transform: Translate { y: -mainFlickable.height/10 * appDrawer.openFactor } scale: (3 - appDrawer.openFactor) /3 //bottomMargin: favoriteStrip.height contentWidth: appletsLayout.width contentHeight: height interactive: !plasmoid.editMode && !launcherDragManager.active signal cancelEditModeForItemsRequested onDragStarted: cancelEditModeForItemsRequested() onDragEnded: cancelEditModeForItemsRequested() onFlickStarted: cancelEditModeForItemsRequested() onFlickEnded: cancelEditModeForItemsRequested() onContentYChanged: MobileShell.HomeScreenControls.homeScreenPosition = contentY DragHandler { target: mainFlickable yAxis.enabled: !appletsLayout.editMode enabled: root.focus && appDrawer.status !== Launcher.AppDrawer.Status.Open onTranslationChanged: { if (active) { appDrawer.offset = -translation.y } } onActiveChanged: { if (!active) { appDrawer.snapDrawerStatus(); } } } NumberAnimation { id: scrollAnim target: mainFlickable properties: "contentX" duration: units.longDuration easing.type: Easing.InOutQuad } // TODO: span on multiple pages DragDrop.DropArea { id: dropArea width: mainFlickable.width height: mainFlickable.height + favoriteStrip.height onDragEnter: { event.accept(event.proposedAction); launcherDragManager.active = true; } onDragMove: { let posInFavorites = favoriteStrip.mapFromItem(this, event.x, event.y); if (posInFavorites.y > 0) { if (plasmoid.nativeInterface.applicationListModel.favoriteCount >= plasmoid.nativeInterface.applicationListModel.maxFavoriteCount ) { launcherDragManager.hideSpacer(); } else { launcherDragManager.showSpacerAtPos(event.x, event.y, favoriteStrip); } appletsLayout.hidePlaceHolder(); } else { appletsLayout.showPlaceHolderAt( Qt.rect(event.x - appletsLayout.defaultItemWidth / 2, event.y - appletsLayout.defaultItemHeight / 2, appletsLayout.defaultItemWidth, appletsLayout.defaultItemHeight) ); launcherDragManager.hideSpacer(); } } onDragLeave: { appletsLayout.hidePlaceHolder(); launcherDragManager.active = false; } preventStealing: true onDrop: { launcherDragManager.active = false; if (event.mimeData.formats[0] === "text/x-plasma-phone-homescreen-launcher") { let storageId = event.mimeData.getDataAsByteArray("text/x-plasma-phone-homescreen-launcher"); let posInFavorites = favoriteStrip.flow.mapFromItem(this, event.x, event.y); if (posInFavorites.y > 0) { if (plasmoid.nativeInterface.applicationListModel.favoriteCount >= plasmoid.nativeInterface.applicationListModel.maxFavoriteCount ) { return; } plasmoid.nativeInterface.applicationListModel.addFavorite(storageId, 0, ApplicationListModel.Favorites) let item = launcherRepeater.itemAt(0); if (item) { item.x = posInFavorites.x; item.y = 0//posInFavorites.y; //launcherDragManager.showSpacer(item, item.width/2, item.height/2); launcherDragManager.dropItem(item, item.width/2, item.height/2); } return; } plasmoid.nativeInterface.applicationListModel.addFavorite(storageId, 0, ApplicationListModel.Desktop) let item = launcherRepeater.itemAt(0); event.accept(event.proposedAction); if (item) { item.x = appletsLayout.placeHolder.x; item.y = appletsLayout.placeHolder.y; appletsLayout.hidePlaceHolder(); launcherDragManager.dropItem(item, appletsLayout.placeHolder.x + appletsLayout.placeHolder.width/2, appletsLayout.placeHolder.y + appletsLayout.placeHolder.height/2); } appletsLayout.hidePlaceHolder(); } else { plasmoid.processMimeData(event.mimeData, event.x - appletsLayout.placeHolder.width / 2, event.y - appletsLayout.placeHolder.height / 2); event.accept(event.proposedAction); appletsLayout.hidePlaceHolder(); } } PlasmaCore.Svg { id: arrowsSvg imagePath: "widgets/arrows" colorGroup: PlasmaCore.Theme.ComplementaryColorGroup } ContainmentLayoutManager.AppletsLayout { id: appletsLayout anchors { fill: parent bottomMargin: favoriteStrip.height } signal appletsLayoutInteracted TapHandler { target: mainFlickable enabled: appDrawer.status !== Launcher.AppDrawer.Status.Open onTapped: { //Hides icons close button appletsLayout.appletsLayoutInteracted(); appletsLayout.editMode = false; } onLongPressed: appletsLayout.editMode = true; onPressedChanged: root.focus = true; } cellWidth: favoriteStrip.cellWidth cellHeight: Math.floor(height / Math.floor(height / favoriteStrip.cellHeight)) configKey: width > height ? "ItemGeometriesHorizontal" : "ItemGeometriesVertical" containment: plasmoid editModeCondition: plasmoid.immutable ? ContainmentLayoutManager.AppletsLayout.Manual : ContainmentLayoutManager.AppletsLayout.AfterPressAndHold // Sets the containment in edit mode when we go in edit mode as well onEditModeChanged: plasmoid.editMode = editMode minimumItemWidth: units.gridUnit * 3 minimumItemHeight: minimumItemWidth defaultItemWidth: units.gridUnit * 6 defaultItemHeight: defaultItemWidth acceptsAppletCallback: function(applet, x, y) { print("Applet: "+applet+" "+x+" "+y) return true; } appletContainerComponent: ContainmentLayoutManager.BasicAppletContainer { id: appletContainer configOverlayComponent: ConfigOverlay {} onEditModeChanged: { launcherDragManager.active = dragActive || editMode; } onDragActiveChanged: { launcherDragManager.active = dragActive || editMode; } } placeHolder: ContainmentLayoutManager.PlaceHolder {} //FIXME: move PlasmaComponents.Label { id: metrics text: "M\nM" visible: false font.pointSize: theme.defaultFont.pointSize * 0.9 } Launcher.LauncherRepeater { id: launcherRepeater cellWidth: appletsLayout.cellWidth cellHeight: appletsLayout.cellHeight appletsLayout: appletsLayout favoriteStrip: favoriteStrip } } } } Launcher.AppDrawer { id: appDrawer anchors.fill: parent topPadding: plasmoid.availableScreenRect.y bottomPadding: favoriteStrip.height + plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y } ScrollIndicator { id: scrollLeftIndicator anchors { left: parent.left leftMargin: units.smallSpacing } elementId: "left-arrow" } ScrollIndicator { id: scrollRightIndicator anchors { right: parent.right rightMargin: units.smallSpacing } elementId: "right-arrow" } Launcher.FavoriteStrip { id: favoriteStrip anchors { left: parent.left right: parent.right bottom: parent.bottom bottomMargin: plasmoid.screenGeometry.height - plasmoid.availableScreenRect.height - plasmoid.availableScreenRect.y } appletsLayout: appletsLayout DragHandler { target: favoriteStrip yAxis.enabled: !appletsLayout.editMode enabled: root.focus && appDrawer.status !== Launcher.AppDrawer.Status.Open onTranslationChanged: { if (active) { appDrawer.offset = -translation.y } } onActiveChanged: { if (!active) { appDrawer.snapDrawerStatus(); } } } TapHandler { target: favoriteStrip onTapped: { //Hides icons close button appletsLayout.appletsLayoutInteracted(); appletsLayout.editMode = false; } onLongPressed: appletsLayout.editMode = true; onPressedChanged: root.focus = true; } } }