/* * Copyright (C) 2023, KylinSoft Co., Ltd. * * 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 3 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, see . * */ import QtQuick 2.15 import QtQml.Models 2.1 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.15 import org.ukui.menu.core 1.0 import org.ukui.menu.extension 1.0 import org.ukui.quick.platform 1.0 as Platform import org.ukui.quick.items 1.0 as UkuiItems import AppControls2 1.0 as AppControls2 GridView { id: favoriteView cellWidth: width / column cellHeight: cellWidth + 12 signal openFolderSignal(string folderId, string folderName, int x, int y) signal contentShowFinished() property bool isContentShow: true property int spacing: 4 property int itemHeight: 84 property int column: 5 property alias viewModel: visualModel property string mergeToAppId: "" property bool isMergeToFolder: false property bool dragTypeIsMerge: false property int exchangedStartIndex: 0 state: isContentShow ? "contentShow" : "contentHidden" states: [ State { name: "contentHidden" PropertyChanges { target: favoriteView; opacity: 0; scale: 0.95 } }, State { name: "contentShow" PropertyChanges { target: favoriteView; opacity: 1; scale: 1 } } ] transitions: [ Transition { to:"contentHidden" SequentialAnimation { PropertyAnimation { properties: "opacity, scale"; duration: 300; easing.type: Easing.InOutCubic } ScriptAction { script: favoriteView.visible = false } } }, Transition { to: "contentShow" PropertyAnimation { properties: "opacity, scale"; duration: 300; easing.type: Easing.InOutCubic } } ] // 按键导航处理(左右键可以循环) focus: true onActiveFocusChanged: currentIndex = 0 onCountChanged: currentIndex = 0 Keys.onRightPressed: { if(currentIndex === count - 1) { currentIndex = 0; return; } currentIndex++; } Keys.onLeftPressed: { if(currentIndex === 0) { currentIndex = count - 1; return; } currentIndex--; } Keys.onDownPressed: { if(currentIndex > count - 1 - column) { return; } currentIndex = currentIndex + column; } Keys.onUpPressed: { if(currentIndex < column) { return; } currentIndex = currentIndex - column; } ScrollBar.vertical: AppControls2.ScrollBar { id: scrollBar visible: viewMouseArea.containsMouse width: 14; height: favoriteView.height } displaced: Transition { NumberAnimation { properties: "x,y"; easing.type: Easing.OutQuad; duration: 200 } } model: DelegateModel { id: visualModel delegate: Item { id: container focus: true width: favoriteView.cellWidth height: favoriteView.cellHeight property int visualIndex: DelegateModel.itemsIndex Binding { target: iconItem.draggedIcon; property: "visualIndex"; value: visualIndex } states: State { when: activeFocus PropertyChanges { target: iconItem alpha: 0.6 } } Keys.onReturnPressed: { var data = {"id": model.id}; send(data); } DropArea { id: delegateDropArea anchors.fill: parent anchors.margins: 14 property string enterSourceId: "" // drag.source [iconItem.draggedIcon] onEntered: { if (drag.source.isFolder) { return; } enterSourceId = drag.source.sourceId; delegateDropTimer.running = true; } onExited: { if (delegateDropTimer.timeOutCount < 1) { dragTypeIsMerge = false; visualModel.items.move(drag.source.visualIndex, iconItem.visualIndex); } delegateDropTimer.running = false; enterSourceId = ""; } } Item { anchors.fill: parent anchors.margins: 2 Timer { id: delegateDropTimer property int timeOutCount: 0 interval: 300 repeat: true onTriggered: { ++timeOutCount; if (timeOutCount == 1) { mergeToAppId = model.id; isMergeToFolder = (model.type === DataType.Folder); dragTypeIsMerge = true; } } onRunningChanged: timeOutCount = 0 } FavoriteDelegate { id: iconItem anchors.fill: parent property int visualIndex: container.DelegateModel.itemsIndex } //编辑模式标志 Loader { id: tag anchors.top: parent.top anchors.right: parent.right anchors.rightMargin: 10 Component { id: editImage UkuiItems.Button { width: 28 height: 28 icon.width: 16 icon.height: 16 background.paletteRole: Platform.Theme.Light background.alpha: 1 activeFocusOnTab: false onClicked: { visualModel.model.removeAppFromFavorites(id); } background.radius: width / 2 icon.source: "ukui-cancel-star-symbolic" } } sourceComponent: mainWindow.editMode && (type === DataType.Normal) ? editImage : null } } } } }