From eeb686aba00ea71ae513bca092a57eae27bfd2e7 Mon Sep 17 00:00:00 2001 From: reionwong Date: Sat, 30 Oct 2021 23:43:12 +0800 Subject: [PATCH] Support drag and drop system tray --- qml/CardItem.qml | 3 +- qml/ControlCenter.qml | 6 ++-- qml/IconButton.qml | 3 +- qml/StandardItem.qml | 12 +++++++ qml/main.qml | 53 ++++++++++++++++++++++++++++++ src/systemtray/systemtraymodel.cpp | 15 +++++++++ src/systemtray/systemtraymodel.h | 2 ++ 7 files changed, 88 insertions(+), 6 deletions(-) diff --git a/qml/CardItem.qml b/qml/CardItem.qml index f02f615..524bca3 100644 --- a/qml/CardItem.qml +++ b/qml/CardItem.qml @@ -59,7 +59,8 @@ Item { Behavior on scale { NumberAnimation { - duration: 100 + duration: 200 + easing.type: Easing.OutSine } } diff --git a/qml/ControlCenter.qml b/qml/ControlCenter.qml index 8a61f15..6ce3bab 100644 --- a/qml/ControlCenter.qml +++ b/qml/ControlCenter.qml @@ -32,7 +32,7 @@ ControlCenterDialog { id: control width: 420 - height: _mainLayout.implicitHeight + FishUI.Units.largeSpacing * 3 + height: _mainLayout.implicitHeight + FishUI.Units.largeSpacing * 2.5 property var margin: 4 * Screen.devicePixelRatio property point position: Qt.point(0, 0) @@ -103,7 +103,7 @@ ControlCenterDialog { Rectangle { id: _background anchors.fill: parent - radius: windowHelper.compositing ? control.height * 0.05 : 0 + radius: windowHelper.compositing ? FishUI.Theme.bigRadius * 1.5 : 0 color: FishUI.Theme.darkMode ? "#4D4D4D" : "#FFFFFF" opacity: windowHelper.compositing ? FishUI.Theme.darkMode ? 0.5 : 0.7 : 1.0 antialiasing: true @@ -115,7 +115,7 @@ ControlCenterDialog { anchors.fill: parent anchors.leftMargin: FishUI.Units.largeSpacing * 1.5 anchors.rightMargin: FishUI.Units.largeSpacing * 1.5 - anchors.topMargin: FishUI.Units.largeSpacing + anchors.topMargin: FishUI.Units.largeSpacing * 1.5 anchors.bottomMargin: FishUI.Units.largeSpacing spacing: FishUI.Units.largeSpacing diff --git a/qml/IconButton.qml b/qml/IconButton.qml index 4a3b42e..e33503a 100644 --- a/qml/IconButton.qml +++ b/qml/IconButton.qml @@ -48,7 +48,6 @@ Item { Rectangle { anchors.fill: parent - anchors.margins: 1 // radius: parent.height * 0.2 radius: parent.height / 2 @@ -67,7 +66,7 @@ Item { Image { id: iconImage anchors.centerIn: parent - width: parent.height * 0.8 + width: parent.height * 0.75 height: width sourceSize.width: width sourceSize.height: height diff --git a/qml/StandardItem.qml b/qml/StandardItem.qml index 71d99d6..609658f 100644 --- a/qml/StandardItem.qml +++ b/qml/StandardItem.qml @@ -36,8 +36,12 @@ Item { property bool checked: false property bool animationEnabled: false + property alias mouseArea: _mouseArea + + signal positionChanged signal clicked signal rightClicked + signal released onCheckedChanged: { _bgRect.state = checked ? "shown" : "hidden" @@ -84,6 +88,10 @@ Item { popupTips.hide() } + onReleased: { + control.released() + } + onContainsMouseChanged: { if (containsMouse && control.popupText !== "") { popupTips.popupText = control.popupText @@ -94,6 +102,10 @@ Item { popupTips.hide() } } + + onPositionChanged: { + control.positionChanged() + } } Rectangle { diff --git a/qml/main.qml b/qml/main.qml index 091f4cd..abff149 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -233,8 +233,20 @@ Item { id: trayModel } + moveDisplaced: Transition { + NumberAnimation { + properties: "x, y" + duration: 200 + easing.type: Easing.InOutQuad + } + } + delegate: StandardItem { + id: _trayItem + property bool darkMode: rootItem.darkMode + property int dragItemIndex: index + property bool dragStarted: false width: trayView.itemWidth height: ListView.view.height @@ -242,6 +254,46 @@ Item { onDarkModeChanged: updateTimer.restart() + Drag.active: _trayItem.mouseArea.drag.active + Drag.dragType: Drag.Automatic + Drag.supportedActions: Qt.MoveAction + Drag.hotSpot.x: iconItem.width / 2 + Drag.hotSpot.y: iconItem.height / 2 + + Drag.onDragStarted: { + dragStarted = true + } + + Drag.onDragFinished: { + dragStarted = false + } + + onPositionChanged: { + if (_trayItem.mouseArea.pressed) { + _trayItem.mouseArea.drag.target = iconItem + iconItem.grabToImage(function(result) { + _trayItem.Drag.imageSource = result.url + }) + } else { + _trayItem.mouseArea.drag.target = null + } + } + + onReleased: { + _trayItem.mouseArea.drag.target = null + } + + DropArea { + anchors.fill: parent + enabled: true + + onEntered: { + if (drag.source) + trayModel.move(drag.source.dragItemIndex, + _trayItem.dragItemIndex) + } + } + Timer { id: updateTimer interval: 10 @@ -256,6 +308,7 @@ Item { source: model.iconName ? model.iconName : model.icon antialiasing: true smooth: false + visible: !dragStarted } onClicked: trayModel.leftButtonClick(model.id) diff --git a/src/systemtray/systemtraymodel.cpp b/src/systemtray/systemtraymodel.cpp index c95a836..18358e3 100644 --- a/src/systemtray/systemtraymodel.cpp +++ b/src/systemtray/systemtraymodel.cpp @@ -127,6 +127,21 @@ void SystemTrayModel::rightButtonClick(const QString &id) } } +void SystemTrayModel::move(int from, int to) +{ + if (from == to) + return; + + m_items.move(from, to); + + if (from < to) + beginMoveRows(QModelIndex(), from, from, QModelIndex(), to + 1); + else + beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); + + endMoveRows(); +} + void SystemTrayModel::onItemAdded(const QString &service) { StatusNotifierItemSource *source = new StatusNotifierItemSource(service, this); diff --git a/src/systemtray/systemtraymodel.h b/src/systemtray/systemtraymodel.h index 291778b..d39030b 100644 --- a/src/systemtray/systemtraymodel.h +++ b/src/systemtray/systemtraymodel.h @@ -53,6 +53,8 @@ public: Q_INVOKABLE void leftButtonClick(const QString &id); Q_INVOKABLE void rightButtonClick(const QString &id); + Q_INVOKABLE void move(int from, int to); + private slots: void onItemAdded(const QString &service); void onItemRemoved(const QString &service);