Warning, /plasma/plasma-mobile/containments/homescreens/halcyon/package/contents/ui/FavoritesAppDelegate.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2022 Devin Lin <espidev@gmail.com> 0002 // SPDX-License-Identifier: GPL-2.0-or-later 0003 0004 import QtQuick 0005 import QtQuick.Layouts 0006 import QtQuick.Controls as Controls 0007 import QtQuick.Effects 0008 0009 import org.kde.plasma.core as PlasmaCore 0010 import org.kde.plasma.components 3.0 as PlasmaComponents 0011 import org.kde.kquickcontrolsaddons 2.0 0012 0013 import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager 0014 import org.kde.plasma.private.mobileshell as MobileShell 0015 import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings 0016 import org.kde.plasma.private.mobileshell.state as MobileShellState 0017 0018 import org.kde.kirigami 2.19 as Kirigami 0019 0020 Item { 0021 id: delegate 0022 0023 property int visualIndex: 0 0024 property real dragFolderAnimationProgress: 0 0025 0026 property list<Kirigami.Action> menuActions 0027 0028 // whether this delegate is a folder 0029 property bool isFolder 0030 0031 // folder object 0032 property var folder 0033 readonly property string folderName: folder ? folder.name : "" 0034 0035 // app object 0036 property var application 0037 readonly property string applicationName: application ? application.name : "" 0038 readonly property string applicationStorageId: application ? application.storageId : "" 0039 readonly property string applicationIcon: application ? application.icon : "" 0040 0041 signal folderOpenRequested() 0042 0043 property alias drag: mouseArea.drag 0044 Drag.active: delegate.drag.active 0045 Drag.source: delegate 0046 Drag.hotSpot.x: delegate.width / 2 0047 Drag.hotSpot.y: delegate.height / 2 0048 0049 // close context menu if drag move 0050 onXChanged: { 0051 if (dialogLoader.item) { 0052 dialogLoader.item.close() 0053 } 0054 } 0055 onYChanged: { 0056 if (dialogLoader.item) { 0057 dialogLoader.item.close() 0058 } 0059 } 0060 0061 function openContextMenu() { 0062 dialogLoader.active = true; 0063 dialogLoader.item.open(); 0064 } 0065 0066 function launch() { 0067 if (isFolder) { 0068 folderOpenRequested(); 0069 } else { 0070 if (application.running) { 0071 launchAppWithAnim(0, 0, "", applicationName, applicationStorageId); 0072 } else { 0073 launchAppWithAnim(delegate.x + (Kirigami.Units.smallSpacing * 2), delegate.y + (Kirigami.Units.smallSpacing * 2), delegate.applicationIcon, applicationName, applicationStorageId); 0074 } 0075 } 0076 } 0077 0078 function launchAppWithAnim(x: int, y: int, source, title: string, storageId: string) { 0079 if (source !== "") { 0080 MobileShellState.ShellDBusClient.openAppLaunchAnimation( 0081 source, 0082 title, 0083 iconLoader.Kirigami.ScenePosition.x + iconLoader.width/2, 0084 iconLoader.Kirigami.ScenePosition.y + iconLoader.height/2, 0085 Math.min(iconLoader.width, iconLoader.height)); 0086 } 0087 0088 application.setMinimizedDelegate(delegate); 0089 MobileShell.AppLaunch.launchOrActivateApp(application.storageId); 0090 } 0091 0092 Loader { 0093 id: dialogLoader 0094 active: false 0095 0096 sourceComponent: PlasmaComponents.Menu { 0097 id: menu 0098 title: label.text 0099 closePolicy: PlasmaComponents.Menu.CloseOnReleaseOutside | PlasmaComponents.Menu.CloseOnEscape 0100 0101 Repeater { 0102 model: menuActions 0103 delegate: PlasmaComponents.MenuItem { 0104 icon.name: modelData.iconName 0105 text: modelData.text 0106 onClicked: modelData.triggered() 0107 } 0108 } 0109 0110 onClosed: dialogLoader.active = false 0111 } 0112 } 0113 0114 MouseArea { 0115 id: mouseArea 0116 0117 anchors.fill: parent 0118 0119 property bool inDrag: false 0120 0121 cursorShape: Qt.PointingHandCursor 0122 acceptedButtons: Qt.LeftButton | Qt.RightButton 0123 onReleased: { 0124 delegate.Drag.drop(); 0125 inDrag = false; 0126 } 0127 onPressAndHold: { inDrag = true; openContextMenu() } 0128 drag.target: inDrag ? delegate : undefined 0129 0130 // grow/shrink animation 0131 property real zoomScale: 1 0132 transform: Scale { 0133 origin.x: mouseArea.width / 2; 0134 origin.y: mouseArea.height / 2; 0135 xScale: mouseArea.zoomScale 0136 yScale: mouseArea.zoomScale 0137 } 0138 0139 property bool launchAppRequested: false 0140 0141 NumberAnimation on zoomScale { 0142 id: shrinkAnim 0143 running: false 0144 duration: ShellSettings.Settings.animationsEnabled ? 80 : 1 0145 to: ShellSettings.Settings.animationsEnabled ? 0.95 : 1 0146 onFinished: { 0147 if (!mouseArea.pressed) { 0148 growAnim.restart(); 0149 } 0150 } 0151 } 0152 0153 NumberAnimation on zoomScale { 0154 id: growAnim 0155 running: false 0156 duration: ShellSettings.Settings.animationsEnabled ? 80 : 1 0157 to: 1 0158 onFinished: { 0159 if (mouseArea.launchAppRequested) { 0160 delegate.launch(); 0161 mouseArea.launchAppRequested = false; 0162 } 0163 } 0164 } 0165 0166 onPressedChanged: { 0167 if (pressed) { 0168 growAnim.stop(); 0169 shrinkAnim.restart(); 0170 } else if (!pressed && !shrinkAnim.running) { 0171 growAnim.restart(); 0172 } 0173 } 0174 0175 // launch app handled by press animation 0176 onClicked: mouse => { 0177 if (mouse.button === Qt.RightButton) { 0178 openContextMenu(); 0179 } else { 0180 launchAppRequested = true; 0181 } 0182 } 0183 0184 HoverHandler { 0185 id: hoverHandler 0186 acceptedDevices: PointerDevice.Mouse 0187 acceptedPointerTypes: PointerDevice.Generic 0188 } 0189 0190 Rectangle { 0191 anchors.fill: parent 0192 radius: height / 2 0193 color: mouseArea.pressed ? Qt.rgba(255, 255, 255, 0.2) : "transparent" 0194 } 0195 0196 RowLayout { 0197 id: rowLayout 0198 anchors { 0199 fill: parent 0200 leftMargin: Kirigami.Units.smallSpacing * 2 0201 topMargin: Kirigami.Units.smallSpacing 0202 rightMargin: Kirigami.Units.smallSpacing * 2 0203 bottomMargin: Kirigami.Units.smallSpacing 0204 } 0205 spacing: 0 0206 0207 Loader { 0208 id: iconLoader 0209 Layout.alignment: Qt.AlignLeft 0210 Layout.minimumWidth: Layout.minimumHeight 0211 Layout.preferredWidth: Layout.minimumHeight 0212 Layout.minimumHeight: parent.height 0213 Layout.preferredHeight: Layout.minimumHeight 0214 0215 sourceComponent: delegate.isFolder ? folderIconComponent : appIconComponent 0216 } 0217 0218 PlasmaComponents.Label { 0219 id: label 0220 visible: text.length > 0 0221 textFormat: Text.MarkdownText 0222 0223 Layout.fillWidth: true 0224 Layout.leftMargin: Kirigami.Units.smallSpacing * 2 0225 Layout.rightMargin: Kirigami.Units.gridUnit 0226 wrapMode: Text.WordWrap 0227 maximumLineCount: 1 0228 elide: Text.ElideRight 0229 0230 text: delegate.isFolder ? delegate.folderName : delegate.applicationName 0231 0232 font.pointSize: Kirigami.Theme.defaultFont.pointSize 0233 font.weight: Font.Bold 0234 color: "white" 0235 0236 layer.enabled: true 0237 layer.effect: MobileShell.TextDropShadow {} 0238 } 0239 0240 Kirigami.Icon { 0241 Layout.alignment: Qt.AlignRight 0242 Layout.preferredWidth: Kirigami.Units.iconSizes.small 0243 Layout.preferredHeight: Kirigami.Units.iconSizes.small 0244 0245 isMask: true 0246 color: 'white' 0247 source: 'arrow-right' 0248 visible: delegate.isFolder 0249 0250 layer.enabled: true 0251 layer.effect: MultiEffect { 0252 shadowEnabled: true 0253 shadowVerticalOffset: 1 0254 blurMax: 8 0255 shadowOpacity: 0.7 0256 } 0257 } 0258 } 0259 } 0260 0261 Component { 0262 id: appIconComponent 0263 0264 Item { 0265 Rectangle { 0266 anchors.fill: parent 0267 anchors.margins: Kirigami.Units.smallSpacing 0268 color: Qt.rgba(255, 255, 255, 0.2) 0269 radius: Kirigami.Units.smallSpacing 0270 opacity: delegate.dragFolderAnimationProgress 0271 } 0272 0273 Kirigami.Icon { 0274 id: icon 0275 anchors.fill: parent 0276 source: delegate.isFolder ? 'document-open-folder' : delegate.applicationIcon 0277 0278 transform: Scale { 0279 origin.x: icon.width / 2 0280 origin.y: icon.height / 2 0281 xScale: 1 - delegate.dragFolderAnimationProgress * 0.5 0282 yScale: 1 - delegate.dragFolderAnimationProgress * 0.5 0283 } 0284 0285 Rectangle { 0286 anchors { 0287 horizontalCenter: parent.horizontalCenter 0288 bottom: parent.bottom 0289 } 0290 visible: application ? application.running : false 0291 radius: width 0292 width: Kirigami.Units.smallSpacing 0293 height: width 0294 color: Kirigami.Theme.highlightColor 0295 } 0296 0297 layer.enabled: true 0298 layer.effect: MultiEffect { 0299 shadowEnabled: true 0300 shadowVerticalOffset: 1 0301 blurMax: 16 0302 shadowOpacity: 0.5 0303 } 0304 } 0305 } 0306 } 0307 0308 Component { 0309 id: folderIconComponent 0310 0311 Item { 0312 Rectangle { 0313 id: rect 0314 anchors.fill: parent 0315 anchors.margins: Kirigami.Units.smallSpacing 0316 color: Qt.rgba(255, 255, 255, 0.2) 0317 radius: Kirigami.Units.smallSpacing 0318 0319 transform: Scale { 0320 origin.x: rect.width / 2 0321 origin.y: rect.height / 2 0322 xScale: 1 + delegate.dragFolderAnimationProgress * 0.5 0323 yScale: 1 + delegate.dragFolderAnimationProgress * 0.5 0324 } 0325 } 0326 0327 Grid { 0328 id: grid 0329 anchors.fill: parent 0330 anchors.margins: Kirigami.Units.smallSpacing * 2 0331 columns: 2 0332 spacing: Kirigami.Units.smallSpacing 0333 0334 property var previews: model.folder.appPreviews 0335 0336 Repeater { 0337 model: grid.previews 0338 delegate: Kirigami.Icon { 0339 implicitWidth: (grid.width - Kirigami.Units.smallSpacing) / 2 0340 implicitHeight: (grid.width - Kirigami.Units.smallSpacing) / 2 0341 source: modelData.icon 0342 0343 layer.enabled: true 0344 layer.effect: MultiEffect { 0345 shadowEnabled: true 0346 shadowVerticalOffset: 1 0347 blurMax: 16 0348 shadowOpacity: 0.6 0349 } 0350 } 0351 } 0352 } 0353 } 0354 } 0355 } 0356 0357 0358