ukui-menu/qml/extensions/FavoriteExtension.qml

232 lines
8.9 KiB
QML
Raw Normal View History

2023-02-22 14:07:53 +08:00
/*
* 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.12
import QtQml.Models 2.1
import QtQuick.Controls 2.5
import org.ukui.menu.core 1.0
import org.ukui.menu.extension 1.0
import AppControls2 1.0 as AppControls2
import org.ukui.quick.platform 1.0 as Platform
import org.ukui.quick.items 1.0 as UkuiItems
2023-02-22 14:07:53 +08:00
UkuiMenuExtension {
Component.onCompleted: {
visualModel.model = extensionData.favoriteAppsModel
}
MouseArea {
id: viewMouseArea
anchors.fill: parent
hoverEnabled: true
UkuiItems.StyleBackground {
anchors.top: parent.top
width: parent.width; height: 1
useStyleTransparency: false
alpha: 0.15
paletteRole: Platform.Theme.Text
visible: favoriteView.contentY > 0
z: 1
}
2023-02-22 14:07:53 +08:00
GridView {
id: favoriteView
anchors.fill: parent
anchors.leftMargin: 16
anchors.topMargin: 12
anchors.bottomMargin: 6
2023-02-22 14:07:53 +08:00
cellWidth: itemHeight + spacing; cellHeight: cellWidth
property int exchangedStartIndex: 0
property int spacing: 4
property int itemHeight: 104
property int column: Math.floor(width / cellWidth)
// 按键导航处理(左右键可以循环)
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;
}
2023-02-22 14:07:53 +08:00
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: DropArea {
id: delegateRoot
property int visualIndex: DelegateModel.itemsIndex
width: favoriteView.cellWidth; height: favoriteView.cellHeight
onEntered: {
visualModel.items.move(drag.source.visualIndex, icon.visualIndex)
}
2023-02-22 14:07:53 +08:00
Binding { target: icon; property: "visualIndex"; value: visualIndex }
focus: true
Keys.onReturnPressed: {
var data = {"id": model.id};
send(data);
}
states: State {
when: delegateRoot.activeFocus
PropertyChanges {
target: icon
alpha: 0.6
}
}
UkuiItems.StyleBackground {
2023-02-22 14:07:53 +08:00
id: icon
height: favoriteView.itemHeight; width: height
property bool hold: false
property int visualIndex: 0
x: 0; y: 0
radius: Platform.Theme.maxRadius
useStyleTransparency: false
2023-02-22 14:07:53 +08:00
scale: icon.hold ? 1.1 :1.0
alpha: control.containsPress ? 0.75 : control.containsMouse ? 0.6 : 0.40
Behavior on scale {
NumberAnimation { duration: 300; easing.type: Easing.InOutCubic }
}
AppControls2.IconLabel {
height: icon.height
width: icon.width - 14
anchors.centerIn: parent
appName: model.name
appIcon: model.icon
display: Display.TextUnderIcon
scale: (control.containsPress && !icon.hold) ? 1.1 : 1.0
2023-06-02 15:44:16 +08:00
ToolTip.visible: textTruncated && control.containsMouse
ToolTip.text: model.name
ToolTip.delay: 500
2023-02-22 14:07:53 +08:00
Behavior on scale {
NumberAnimation { duration: 300; easing.type: Easing.InOutCubic }
}
}
MouseArea {
id: control
anchors.fill: parent
hoverEnabled: true
pressAndHoldInterval: 300
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
2023-04-04 17:20:25 +08:00
if (mouse.button === Qt.RightButton) {
visualModel.model.openMenu(index)
} else if (mouse.button === Qt.LeftButton) {
2023-02-22 14:07:53 +08:00
var data = {"id": model.id};
send(data);
}
}
onPressAndHold: {
if (mouse.button === Qt.LeftButton) {
drag.target = icon;
icon.hold = true;
favoriteView.exchangedStartIndex = icon.visualIndex;
}
}
onReleased: {
icon.hold = false;
drag.target = null;
}
}
onHoldChanged: {
if (hold) {
favoriteView.interactive = false;
} else {
favoriteView.interactive = true;
visualModel.model.exchangedAppsOrder(favoriteView.exchangedStartIndex, icon.visualIndex);
}
}
Drag.active: control.drag.active
Drag.source: icon
Drag.hotSpot.x: icon.width / 2
Drag.hotSpot.y: icon.height / 2
Drag.onActiveChanged: {
if (Drag.active) {
icon.parent = favoriteView;
} else {
iconResetAnimation.start();
}
}
ParallelAnimation {
id: iconResetAnimation
NumberAnimation {
target: icon
property: "x"
to: delegateRoot.x
easing.type: Easing.OutQuad
duration: 300
}
NumberAnimation {
target: icon
property: "y"
to: delegateRoot.y - favoriteView.contentY
easing.type: Easing.OutQuad
duration: 300
}
2023-02-22 14:07:53 +08:00
onFinished: {
icon.parent = delegateRoot;
icon.x = 0; icon.y = 0;
}
}
}
}
}
}
}
}