Warning, /plasma/plasma-mobile/containments/homescreens/folio/package/contents/ui/HomeScreenPage.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 import QtQuick
0005 import QtQuick.Window
0006 import QtQuick.Layouts
0007 import QtQuick.Effects
0008 
0009 import org.kde.plasma.components 3.0 as PC3
0010 import org.kde.plasma.private.mobileshell.state as MobileShellState
0011 import org.kde.plasma.private.mobileshell as MobileShell
0012 import org.kde.private.mobile.homescreen.folio 1.0 as Folio
0013 import org.kde.kirigami as Kirigami
0014 
0015 import "./delegate"
0016 import "./private"
0017 
0018 Item {
0019     id: root
0020 
0021     property int pageNum
0022 
0023     property var pageModel
0024     property var homeScreen
0025 
0026     // background when in settings view (for rearranging pages)
0027     Rectangle {
0028         id: settingsViewBackground
0029         anchors.fill: parent
0030         color: Qt.rgba(255, 255, 255, 0.2)
0031         opacity: Folio.HomeScreenState.settingsOpenProgress
0032         radius: Kirigami.Units.largeSpacing
0033     }
0034 
0035     // square that shows when hovering over a spot to drop a delegate on
0036     PlaceholderDelegate {
0037         id: dragDropFeedback
0038         width: Folio.HomeScreenState.pageCellWidth
0039         height: Folio.HomeScreenState.pageCellHeight
0040 
0041         property var dropPosition: Folio.HomeScreenState.dragState.candidateDropPosition
0042         property var dropDelegate: Folio.HomeScreenState.dragState.dropDelegate
0043         property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
0044 
0045         // only show if it is an empty spot on this page
0046         visible: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
0047                     dropPosition.location === Folio.DelegateDragPosition.Pages &&
0048                     dropPosition.page === root.pageNum &&
0049                     !dropDelegateIsWidget &&
0050                     Folio.HomeScreenState.getPageDelegateAt(root.pageNum, dropPosition.pageRow, dropPosition.pageColumn) === null
0051 
0052         x: dropPosition.pageColumn * Folio.HomeScreenState.pageCellWidth
0053         y: dropPosition.pageRow * Folio.HomeScreenState.pageCellHeight
0054     }
0055 
0056     // square that shows when a widget hovers over a spot to drop a delegate on
0057     Rectangle {
0058         id: widgetDragDropFeedback
0059         width: (dropDelegateIsWidget ? dropDelegate.widget.gridWidth : 0) * Folio.HomeScreenState.pageCellWidth
0060         height: (dropDelegateIsWidget ? dropDelegate.widget.gridHeight : 0) * Folio.HomeScreenState.pageCellHeight
0061 
0062         property var dropPosition: Folio.HomeScreenState.dragState.candidateDropPosition
0063         property var dropDelegate: Folio.HomeScreenState.dragState.dropDelegate
0064         property bool dropDelegateIsWidget: dropDelegate && dropDelegate.type === Folio.FolioDelegate.Widget
0065 
0066         // only show if the widget can be placed here
0067         visible: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
0068                     dropPosition.location === Folio.DelegateDragPosition.Pages &&
0069                     dropPosition.page === root.pageNum &&
0070                     dropDelegateIsWidget &&
0071                     pageModel.canAddDelegate(dropPosition.pageRow, dropPosition.pageColumn, dropDelegate)
0072 
0073         radius: Kirigami.Units.smallSpacing
0074         color: Qt.rgba(255, 255, 255, 0.3)
0075 
0076         x: dropPosition.pageColumn * Folio.HomeScreenState.pageCellWidth
0077         y: dropPosition.pageRow * Folio.HomeScreenState.pageCellHeight
0078 
0079         layer.enabled: true
0080         layer.effect: DelegateShadow {}
0081     }
0082 
0083     // repeater of all delegates in the page
0084     Repeater {
0085         model: root.pageModel
0086 
0087         delegate: Item {
0088             id: delegate
0089 
0090             property Folio.FolioPageDelegate pageDelegate: model.delegate
0091             property int row: pageDelegate.row
0092             property int column: pageDelegate.column
0093 
0094             property var dragState: Folio.HomeScreenState.dragState
0095 
0096             property bool isDropPositionThis: dragState.candidateDropPosition.location === Folio.DelegateDragPosition.Pages &&
0097                                               dragState.candidateDropPosition.page === root.pageNum &&
0098                                               dragState.candidateDropPosition.pageRow === delegate.pageDelegate.row &&
0099                                               dragState.candidateDropPosition.pageColumn === delegate.pageDelegate.column
0100 
0101             property bool isAppHoveredOver: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
0102                                             dragState.dropDelegate &&
0103                                             dragState.dropDelegate.type === Folio.FolioDelegate.Application &&
0104                                             isDropPositionThis
0105 
0106             implicitWidth: loader.item ? loader.item.implicitWidth : 0
0107             implicitHeight: loader.item ? loader.item.implicitHeight : 0
0108             width: loader.item ? loader.item.width : 0
0109             height: loader.item ? loader.item.height : 0
0110 
0111             x: column * Folio.HomeScreenState.pageCellWidth
0112             y: row * Folio.HomeScreenState.pageCellHeight
0113 
0114             visible: row >= 0 && row < Folio.HomeScreenState.pageRows &&
0115                      column >= 0 && column < Folio.HomeScreenState.pageColumns
0116 
0117             Loader {
0118                 id: loader
0119                 anchors.top: parent.top
0120                 anchors.left: parent.left
0121 
0122                 sourceComponent: {
0123                     if (delegate.pageDelegate.type === Folio.FolioDelegate.Application) {
0124                         return appComponent;
0125                     } else if (delegate.pageDelegate.type === Folio.FolioDelegate.Folder) {
0126                         return folderComponent;
0127                     } else if (delegate.pageDelegate.type === Folio.FolioDelegate.Widget) {
0128                         return widgetComponent;
0129                     } else {
0130                         return noneComponent;
0131                     }
0132                 }
0133             }
0134 
0135             Component {
0136                 id: noneComponent
0137 
0138                 Item {}
0139             }
0140 
0141             Component {
0142                 id: appComponent
0143 
0144                 AppDelegate {
0145                     id: appDelegate
0146                     name: Folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.application.name : ""
0147                     application: delegate.pageDelegate.application
0148                     turnToFolder: delegate.isAppHoveredOver
0149                     turnToFolderAnimEnabled: Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate
0150 
0151                     implicitWidth: Folio.HomeScreenState.pageCellWidth
0152                     implicitHeight: Folio.HomeScreenState.pageCellHeight
0153                     width: Folio.HomeScreenState.pageCellWidth
0154                     height: Folio.HomeScreenState.pageCellHeight
0155 
0156                     // do not show if the drop animation is running to this delegate
0157                     visible: !(root.homeScreen.dropAnimationRunning && delegate.isDropPositionThis)
0158 
0159                     // don't show label in drag and drop mode
0160                     labelOpacity: delegate.opacity
0161 
0162                     onPressAndHold: {
0163                         let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, appDelegate.delegateItem);
0164                         Folio.HomeScreenState.startDelegatePageDrag(
0165                             mappedCoords.x,
0166                             mappedCoords.y,
0167                             appDelegate.pressPosition.x,
0168                             appDelegate.pressPosition.y,
0169                             root.pageNum,
0170                             delegate.pageDelegate.row,
0171                             delegate.pageDelegate.column
0172                         );
0173 
0174                         contextMenu.open();
0175                     }
0176                     onPressAndHoldReleased: {
0177                         // cancel the event if the delegate is not dragged
0178                         if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
0179                             homeScreen.cancelDelegateDrag();
0180                         }
0181                     }
0182 
0183                     onRightMousePress: {
0184                         contextMenu.open();
0185                     }
0186 
0187                     // TODO don't use loader, and move outside to a page to make it more performant
0188                     ContextMenuLoader {
0189                         id: contextMenu
0190 
0191                         // close menu when drag starts
0192                         Connections {
0193                             target: Folio.HomeScreenState
0194 
0195                             function onSwipeStateChanged() {
0196                                 if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
0197                                     contextMenu.close();
0198                                 }
0199                             }
0200                         }
0201 
0202                         actions: [
0203                             Kirigami.Action {
0204                                 icon.name: "emblem-favorite"
0205                                 text: i18n("Remove")
0206                                 onTriggered: root.pageModel.removeDelegate(delegate.row, delegate.column)
0207                             }
0208                         ]
0209                     }
0210                 }
0211             }
0212 
0213             Component {
0214                 id: folderComponent
0215 
0216                 AppFolderDelegate {
0217                     id: appFolderDelegate
0218                     name: Folio.FolioSettings.showPagesAppLabels ? delegate.pageDelegate.folder.name : ""
0219                     folder: delegate.pageDelegate.folder
0220 
0221                     implicitWidth: Folio.HomeScreenState.pageCellWidth
0222                     implicitHeight: Folio.HomeScreenState.pageCellHeight
0223                     width: Folio.HomeScreenState.pageCellWidth
0224                     height: Folio.HomeScreenState.pageCellHeight
0225 
0226                     // do not show if the drop animation is running to this delegate, and the drop delegate is a folder
0227                     visible: !(root.homeScreen.dropAnimationRunning &&
0228                                delegate.isDropPositionThis &&
0229                                delegate.dragState.dropDelegate.type === Folio.FolioDelegate.Folder)
0230 
0231                     // don't show label in drag and drop mode
0232                     labelOpacity: delegate.opacity
0233 
0234                     appHoveredOver: delegate.isAppHoveredOver
0235 
0236                     onAfterClickAnimation: {
0237                         const pos = homeScreen.prepareFolderOpen(appFolderDelegate.contentItem);
0238                         Folio.HomeScreenState.openFolder(pos.x, pos.y, folder);
0239                     }
0240 
0241                     onPressAndHold: {
0242                         let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, appFolderDelegate.delegateItem);
0243                         Folio.HomeScreenState.startDelegatePageDrag(
0244                             mappedCoords.x,
0245                             mappedCoords.y,
0246                             appFolderDelegate.pressPosition.x,
0247                             appFolderDelegate.pressPosition.y,
0248                             root.pageNum,
0249                             delegate.pageDelegate.row,
0250                             delegate.pageDelegate.column
0251                         );
0252 
0253                         contextMenu.open();
0254                     }
0255 
0256                     onPressAndHoldReleased: {
0257                         // cancel the event if the delegate is not dragged
0258                         if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
0259                             homeScreen.cancelDelegateDrag();
0260                         }
0261                     }
0262 
0263                     onRightMousePress: {
0264                         contextMenu.open();
0265                     }
0266 
0267                     // TODO don't use loader, and move outside to a page to make it more performant
0268                     ContextMenuLoader {
0269                         id: contextMenu
0270 
0271                         // close menu when drag starts
0272                         Connections {
0273                             target: Folio.HomeScreenState
0274 
0275                             function onSwipeStateChanged() {
0276                                 if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate) {
0277                                     contextMenu.close();
0278                                 }
0279                             }
0280                         }
0281 
0282                         actions: [
0283                             Kirigami.Action {
0284                                 icon.name: "emblem-favorite"
0285                                 text: i18n("Remove")
0286                                 onTriggered: root.pageModel.removeDelegate(delegate.row, delegate.column)
0287                             }
0288                         ]
0289                     }
0290                 }
0291             }
0292 
0293             Component {
0294                 id: widgetComponent
0295 
0296                 WidgetDelegate {
0297                     id: widgetDelegate
0298 
0299                     // don't reparent applet if the drop animation is running to this delegate
0300                     // background: there is only one "visual" instance of the widget, once this delegate loads
0301                     //             it will reparent it to here (but we don't want it to happen while the drop animation is running)
0302                     property bool suppressAppletReparent: (root.homeScreen.currentlyDraggedWidget === delegate.pageDelegate.widget)
0303                                                             && delegate.isDropPositionThis
0304 
0305                     visible: !suppressAppletReparent
0306                     widget: suppressAppletReparent ? null : delegate.pageDelegate.widget
0307 
0308                     onStartEditMode: (pressPoint) => {
0309                         let mappedCoords = root.homeScreen.prepareStartDelegateDrag(delegate.pageDelegate, widgetDelegate);
0310                         Folio.HomeScreenState.startDelegatePageDrag(
0311                             mappedCoords.x,
0312                             mappedCoords.y,
0313                             pressPoint.x - mappedCoords.x,
0314                             pressPoint.y - mappedCoords.y,
0315                             root.pageNum,
0316                             delegate.pageDelegate.row,
0317                             delegate.pageDelegate.column
0318                         );
0319 
0320                         widgetConfig.startOpen();
0321                     }
0322 
0323                     onPressReleased: {
0324                         // cancel the event if the delegate is not dragged
0325                         if (Folio.HomeScreenState.swipeState === Folio.HomeScreenState.AwaitingDraggingDelegate) {
0326                             Folio.HomeScreenState.cancelDelegateDrag();
0327                             widgetConfig.fullyOpen();
0328                         }
0329                     }
0330 
0331                     layer.enabled: widgetDelegate.editMode
0332                     layer.effect: DarkenEffect {}
0333 
0334                     PC3.ToolTip {
0335                         visible: widgetDelegate.editMode && pressed
0336                         text: i18n('Release to configure, drag to move')
0337                     }
0338 
0339                     WidgetDelegateConfig {
0340                         id: widgetConfig
0341                         homeScreen: root.homeScreen
0342 
0343                         pageModel: root.pageModel
0344                         pageDelegate: delegate.pageDelegate
0345                         widget: delegate.pageDelegate.widget
0346 
0347                         pageNum: root.pageNum
0348                         row: delegate.row
0349                         column: delegate.column
0350 
0351                         widgetWidth: widgetDelegate.widgetWidth
0352                         widgetHeight: widgetDelegate.widgetHeight
0353                         widgetX: delegate.x + root.anchors.leftMargin + root.homeScreen.leftMargin
0354                         widgetY: delegate.y + root.anchors.topMargin + root.homeScreen.topMargin
0355 
0356                         topWidgetBackgroundPadding: widgetDelegate.topWidgetBackgroundPadding
0357                         bottomWidgetBackgroundPadding: widgetDelegate.bottomWidgetBackgroundPadding
0358                         leftWidgetBackgroundPadding: widgetDelegate.leftWidgetBackgroundPadding
0359                         rightWidgetBackgroundPadding: widgetDelegate.rightWidgetBackgroundPadding
0360 
0361                         anchors.fill: parent
0362 
0363                         onRemoveRequested: {
0364                             if (widget.applet) {
0365                                 widget.destroyApplet();
0366                             }
0367                             root.pageModel.removeDelegate(delegate.row, delegate.column);
0368                         }
0369 
0370                         onClosed: widgetDelegate.editMode = false
0371                     }
0372                 }
0373             }
0374         }
0375     }
0376 }