ukui-menu/qml/extensions/FavoriteGridView.qml

219 lines
6.9 KiB
QML
Raw Normal View History

/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
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 + 8
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
}
}
}
}
}