/* * SPDX-FileCopyrightText: 2019 Marco Martin * * SPDX-License-Identifier: LGPL-2.0-or-later */ 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 //TODO: everything using this will eventually move in Launcher import "launcher/private" as LauncherPrivate 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)); } function snapPage() { scrollAnim.running = false; scrollAnim.to = mainFlickable.width * Math.round(mainFlickable.contentX / mainFlickable.width) scrollAnim.running = true; } //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 interactive: false signal cancelEditModeForItemsRequested onDragStarted: cancelEditModeForItemsRequested() onDragEnded: cancelEditModeForItemsRequested() onFlickStarted: cancelEditModeForItemsRequested() onFlickEnded: cancelEditModeForItemsRequested() onContentYChanged: MobileShell.HomeScreenControls.homeScreenPosition = contentY LauncherPrivate.DragGestureHandler { id: gestureHandler target: appletsLayout appDrawer: appDrawer mainFlickable: mainFlickable enabled: root.focus && appDrawer.status !== Launcher.AppDrawer.Status.Open && !appletsLayout.editMode && !plasmoid.editMode && !launcherDragManager.active onSnapPage: root.snapPage(); } NumberAnimation { id: scrollAnim target: mainFlickable properties: "contentX" duration: units.longDuration easing.type: Easing.InOutQuad } // TODO: span on multiple pages DragDrop.DropArea { id: dropArea width: Math.max(mainFlickable.width, mainFlickable.width * Math.ceil(appletsLayout.childrenRect.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; } let pos = Math.min(plasmoid.nativeInterface.applicationListModel.count, Math.floor(posInFavorites.x/favoriteStrip.cellWidth)) plasmoid.nativeInterface.applicationListModel.addFavorite(storageId, pos, ApplicationListModel.Favorites) let item = launcherRepeater.itemAt(pos); 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; } let pos = plasmoid.nativeInterface.applicationListModel.count; plasmoid.nativeInterface.applicationListModel.addFavorite(storageId, pos, ApplicationListModel.Desktop) let item = launcherRepeater.itemAt(pos); 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 } } } PlasmaComponents.PageIndicator { anchors { bottom: parent.bottom horizontalCenter: parent.horizontalCenter bottomMargin: PlasmaCore.Units.gridUnit * 2 } PlasmaCore.ColorScope.inherit: false PlasmaCore.ColorScope.colorGroup: PlasmaCore.Theme.ComplementaryColorGroup parent: mainFlickable count: Math.ceil(dropArea.width / mainFlickable.width) visible: count > 1 currentIndex: Math.round(mainFlickable.contentX / mainFlickable.width) } } 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 LauncherPrivate.DragGestureHandler { target: favoriteStrip appDrawer: appDrawer mainFlickable: mainFlickable enabled: root.focus && appDrawer.status !== Launcher.AppDrawer.Status.Open && !appletsLayout.editMode && !plasmoid.editMode && !launcherDragManager.active onSnapPage: root.snapPage(); } TapHandler { target: favoriteStrip onTapped: { //Hides icons close button appletsLayout.appletsLayoutInteracted(); appletsLayout.editMode = false; } onLongPressed: appletsLayout.editMode = true; onPressedChanged: root.focus = true; } } }