Skip to content

Commit

Permalink
feat: dnd multi selected item
Browse files Browse the repository at this point in the history
add DragItemsImage to Generate a thumbnail of dragged items
  • Loading branch information
kegechen committed Aug 6, 2024
1 parent 7032223 commit cac96ab
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 15 deletions.
1 change: 1 addition & 0 deletions qt6/src/qml.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ set(QML_DTK_CONTROLS
"qml/PlaceholderText.qml"
"qml/ControlGroup.qml"
"qml/ControlGroupItem.qml"
"qml/DragItemsImage.qml"
)

foreach(QML_FILE ${QML_DTK_CONTROLS})
Expand Down
79 changes: 79 additions & 0 deletions qt6/src/qml/DragItemsImage.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

import QtQuick 2.15

Item {
id: control
property list<Item> items

signal aboutToGrabToImage(Item item)
signal grabToImageFinished(Item item)

onItemsChanged: function updateGeomotry() {
var w = 0
var h = 0
for (var i = 0; i < control.items.length; ++i) {
let item = control.items[i]
w = Math.max(w, item.width)
h = Math.max(h, item.height)
}
control.width = w + 30
control.height = h * 2 + 30
}

function addItem(item) {
if (control.items.include(item))
return

items.push(item)
}

function removeItem(item) {
if (!control.items.include(item))
return

var index = control.items.indexOf(item);
if (index !== -1) {
control.items.splice(index, 1);
}
}

Repeater {
model: control.items.length
delegate: Image {
id: img
anchors.centerIn: parent
antialiasing: true
rotation: index ? (index % 2 === 0 ? 10 : -10) : 0
opacity: (1 - index * 0.2)
z: -index

Component.onCompleted: {
let item = control.items[index]
if (!item)
return

// item.dragActive = true
aboutToGrabToImage(item)
item.grabToImage(function(result) {
img.source = result.url
grabToImageFinished(item)
})
}
}
}

RoundButton {
id: number
checked: true
anchors.right: dragItem.right
anchors.top: dragItem.top
anchors.margins: 8
implicitWidth: 24
implicitHeight: 24
text: control.items.length > 1 ? control.items.length : ""
opacity: control.items.length > 1 ? 1 : 0
}
}
61 changes: 57 additions & 4 deletions qt6/src/qml/ItemDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later

import QtQuick 2.11
import QtQuick
import QtQuick.Templates as T
import QtQuick.Layouts 1.11
import org.deepin.dtk 1.0 as D
Expand All @@ -18,6 +18,12 @@ T.ItemDelegate {
property Component content
property D.Palette checkedTextColor: DS.Style.checkedButton.text
property int corners: D.RoundRectangle.TopLeftCorner | D.RoundRectangle.TopRightCorner | D.RoundRectangle.BottomLeftCorner | D.RoundRectangle.BottomRightCorner
property bool dragActive: false
// drag
property bool enableDrag: false
Drag.mimeData: { "text/plain": control.text }
Drag.dragType: Drag.Automatic

function getCornersForBackground(index, count) {
if (count <= 1)
return D.RoundRectangle.TopLeftCorner | D.RoundRectangle.TopRightCorner | D.RoundRectangle.BottomLeftCorner | D.RoundRectangle.BottomRightCorner
Expand All @@ -36,7 +42,7 @@ T.ItemDelegate {
spacing: DS.Style.control.spacing
checkable: true
autoExclusive: true
palette.windowText: checked && !control.cascadeSelected && control.backgroundVisible ? D.ColorSelector.checkedTextColor : undefined
palette.windowText: checked && !control.cascadeSelected && control.backgroundVisible && !dragActive? D.ColorSelector.checkedTextColor : undefined

D.DciIcon.mode: D.ColorSelector.controlState
D.DciIcon.theme: D.ColorSelector.controlTheme
Expand Down Expand Up @@ -90,7 +96,7 @@ T.ItemDelegate {

Loader {
anchors.fill: parent
active: checked && !control.cascadeSelected
active: checked && !control.cascadeSelected && !dragActive
sourceComponent: HighlightPanel {}
}

Expand All @@ -103,13 +109,60 @@ T.ItemDelegate {
corners: control.corners
}
}

Loader {
anchors.fill: parent
active: !control.ListView.view && !checked && control.backgroundVisible
sourceComponent: D.RoundRectangle {
color: DS.Style.itemDelegate.normalColor
radius: DS.Style.control.radius
corners: control.corners
}
}

Loader {
anchors.fill: parent
active: dragActive
sourceComponent: Rectangle {
border.color: Qt.rgba(0, 0, 0, 0.09)
radius: DS.Style.control.radius
}
}
}

DragHandler {
id: dragHandler
enabled: enableDrag
onActiveChanged: {
if (active) {
let dragItem = control.ListView.view.dragItem
if (!dragItem)
return

let md = JSON.stringify(dragItem.Drag.mimeData)

if (md.length > 2) // '{}'
control.Drag.mimeData = dragItem.Drag.mimeData

dragItem.grabToImage(function(result) {
control.Drag.imageSource = result.url;
control.Drag.hotSpot = Qt.point(dragItem.width / 2, dragItem.height / 2)
control.Drag.active = true
})
}
}
}

onHoveredChanged: {
if (checked || control.cascadeSelected || !backgroundVisible)
if (checked || control.cascadeSelected || !backgroundVisible || dragActive)
return

if (ListView.view)
ListView.view.setHoverItem(control.hovered ? control : null)
}

onCheckedChanged: {
if (ListView.view)
ListView.view.updateCheckedItems()
}
}
51 changes: 40 additions & 11 deletions qt6/src/qml/ListView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later

import QtQuick 2.11
import QtQuick 2.15
import QtQuick.Templates as T
import org.deepin.dtk 1.0 as D
import org.deepin.dtk.style 1.0 as DS
import org.deepin.dtk.private 1.0 as P

Expand All @@ -12,16 +13,8 @@ ListView {
property int duration: 100
property bool bgVisible: false
property Item hoveredItem

onContentXChanged: {
if (hoveredItem && hoveredItem.hovered && background)
background.x = hoveredItem.x - contentX
}

onContentYChanged: {
if (hoveredItem && hoveredItem.hovered && background)
background.y = hoveredItem.y - contentY
}
property list<Item> checkedItems
property alias dragItem: dragItem

function setHoverItem(item) {
if (item) {
Expand All @@ -39,6 +32,42 @@ ListView {
}
}

function updateCheckedItems() {
var items = []
for (var i = 0; i < count; ++i) {
let item = itemAtIndex(i)
if (item && item.checked) {
items.push(item)
}
}

checkedItems = items
}

DragItemsImage {
id: dragItem
items: checkedItems
visible: Drag.active
// Drag.mimeData: {"text/plain": ""}

onAboutToGrabToImage: function(item) {
item.dragActive = true
}
onGrabToImageFinished: function(item) {
item.dragActive = false
}
}

onContentXChanged: {
if (hoveredItem && hoveredItem.hovered && background)
background.x = hoveredItem.x - contentX
}

onContentYChanged: {
if (hoveredItem && hoveredItem.hovered && background)
background.y = hoveredItem.y - contentY
}

// ItemDelegate hover item0 ==> item1, add timer ignore [item0.unhovered]
// item0.hovered, item0.unhovered, item1.hovered
Timer {
Expand Down

0 comments on commit cac96ab

Please sign in to comment.