This commit is contained in:
zhuzichu 2023-09-19 18:31:29 +08:00
parent 66ae37a023
commit 7ad8c969da
4 changed files with 233 additions and 51 deletions

View File

@ -102,6 +102,18 @@ FluScrollablePage {
text:"draggable"
checked: true
}
FluButton{
text:"all expand"
onClicked: {
tree_view.allExpand()
}
}
FluButton{
text:"all collapse"
onClicked: {
tree_view.allCollapse()
}
}
}
}
CodeExpander{
@ -119,4 +131,3 @@ FluScrollablePage {
'
}
}

View File

@ -200,8 +200,12 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
}
}
srcChildren->removeAt(srcIndex);
destChildren->insert(destIndex+1,dragItem);
int offset = 1;
int offset = 0;
if(!isDropTopArea){
offset = offset + 1;
}
destChildren->insert(destIndex+offset,dragItem);
offset = 1;
if(isDropTopArea){
offset = offset - 1;
}
@ -211,10 +215,10 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
}
bool FluTreeModel::hitHasChildrenExpanded(int row){
auto itemData = _rows.at(row);
if(itemData->hasChildren() && itemData->_isExpanded){
return true;
}
// auto itemData = _rows.at(row);
// if(itemData->hasChildren() && itemData->_isExpanded){
// return true;
// }
return false;
}

View File

@ -16,10 +16,13 @@ Item {
id:d
property var current
property int dropIndex: -1
property var hoverItem
property int hoverIndex: -1
property bool itemPress: false
property bool itemDragActive: false
property bool isDropTopArea: false
property int dragIndex: -1
property color hitColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark
}
onDataSourceChanged: {
tree_model.setDataSource(dataSource)
@ -41,6 +44,7 @@ Item {
signal pooled
onReused: {
console.debug(itemModel.title)
}
onPooled: {
}
@ -83,6 +87,7 @@ Item {
drag.target:control.draggable ? loader_container : undefined
hoverEnabled: true
drag.onActiveChanged: {
d.itemDragActive = drag.active
if(drag.active){
if(itemModel.isExpanded && itemModel.hasChildren()){
tree_model.collapse(rowIndex)
@ -93,6 +98,7 @@ Item {
}
onPressed:
(mouse)=>{
d.itemPress = true
clickPos = Qt.point(mouse.x,mouse.y)
console.debug(clickPos)
loader_container.itemControl = itemControl
@ -100,8 +106,8 @@ Item {
var cellPosition = item_container.mapToItem(table_view, 0, 0)
loader_container.width = item_container.width
loader_container.height = item_container.height
loader_container.x = table_view.contentX + cellPosition.x
loader_container.y = table_view.contentY + cellPosition.y
loader_container.x = cellPosition.x
loader_container.y = cellPosition.y
}
onClicked: {
d.current = itemModel
@ -111,17 +117,21 @@ Item {
item_container.toggle()
}
}
onExited: {
d.hoverIndex = -1
}
onPositionChanged:
(mouse)=> {
if(!drag.active){
return
}
var cellPosition = item_container.mapToItem(table_view, 0, 0)
if(mouse.y+cellPosition.y<0 || mouse.y+cellPosition.y>table_view.height){
d.hoverItem = undefined
d.hoverIndex = -1
d.dropIndex = -1
return
}
if((mouse.x-table_view.contentX)>table_view.width || (mouse.x-table_view.contentX)<0){
d.hoverItem = undefined
d.hoverIndex = -1
d.dropIndex = -1
return
}
@ -129,6 +139,16 @@ Item {
var viewPos = table_view.mapToGlobal(0,0)
var y = table_view.contentY + pos.y-viewPos.y
var index = Math.floor(y/30)
if(item_mouse.pressed){
d.hoverItem = undefined
d.hoverIndex = -1
}else{
d.hoverItem = item_container
d.hoverIndex = index
}
if(!drag.active){
return
}
if(tree_model.hitHasChildrenExpanded(index) && y>index*30+15){
d.dropIndex = index + 1
d.isDropTopArea = true
@ -143,10 +163,12 @@ Item {
}
onCanceled: {
loader_container.sourceComponent = undefined
d.itemPress = false
d.dropIndex = -1
d.dragIndex = -1
}
onReleased: {
d.itemPress = false
loader_container.sourceComponent = undefined
if(d.dropIndex !== -1){
tree_model.dragAnddrop(d.dragIndex,d.dropIndex,d.isDropTopArea)
@ -155,6 +177,7 @@ Item {
d.dragIndex = -1
}
}
Drag.dragType: Drag.None
Drag.active: item_mouse.drag.active
Rectangle{
id:item_line_drop_tip
@ -255,17 +278,11 @@ Item {
if(isCurrent){
return Qt.rgba(1,1,1,0.03)
}
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0)
}else{
if(isCurrent){
return Qt.rgba(0,0,0,0.06)
}
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0)
}
}
@ -275,18 +292,26 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 14 + 30*itemModel.depth
FluIconButton{
Item{
opacity: itemModel.hasChildren()
Layout.preferredWidth: 20
Layout.preferredHeight: 20
enabled: opacity
opacity: itemModel.hasChildren()
contentItem: FluIcon{
TapHandler{
enabled: parent.opacity
onSingleTapped: {
item_container.toggle()
}
}
MouseArea{
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
anchors.fill: parent
}
FluIcon{
rotation: itemModel.isExpanded?0:-90
iconSource:FluentIcons.ChevronDown
iconSize: 16
}
onClicked: {
item_container.toggle()
anchors.centerIn: parent
}
}
Item{
@ -299,9 +324,6 @@ Item {
text: itemModel.title
anchors.centerIn: parent
color:{
if(item_mouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
@ -309,10 +331,65 @@ Item {
}
}
}
Component{
id:com_background
Item{
Rectangle{
radius: 4
anchors{
fill: parent
leftMargin: 6
rightMargin: 6
}
color:{
if(FluTheme.dark){
if(d.itemPress){
return Qt.rgba(1,1,1,0.06)
}
return Qt.rgba(1,1,1,0.03)
}else{
if(d.itemPress){
return Qt.rgba(0,0,0,0.06)
}
return Qt.rgba(0,0,0,0.03)
}
}
}
}
}
ScrollView{
id:scroll_view
anchors.fill: parent
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
Loader{
id:loader_background
y:{
if(d.hoverItem){
var cellPosition = d.hoverItem.mapToItem(table_view, 0, 0)
return cellPosition.y
}
return 0
}
width: {
if(d.hoverItem){
return d.hoverItem.width
}
return 0
}
height: {
if(d.hoverItem){
return d.hoverItem.height
}
return 0
}
sourceComponent: {
if(d.hoverIndex === -1 || d.itemDragActive){
return undefined
}
return com_background
}
}
TableView{
id:table_view
ScrollBar.horizontal: FluScrollBar{}
@ -360,4 +437,17 @@ Item {
function visibleCount(){
return table_view.rows
}
function collapse(rowIndex){
tree_model.collapse(rowIndex)
}
function expand(rowIndex){
tree_model.expand(rowIndex)
}
function allExpand(){
tree_model.allExpand()
}
function allCollapse(){
tree_model.allCollapse()
}
}

View File

@ -16,10 +16,13 @@ Item {
id:d
property var current
property int dropIndex: -1
property var hoverItem
property int hoverIndex: -1
property bool itemPress: false
property bool itemDragActive: false
property bool isDropTopArea: false
property int dragIndex: -1
property color hitColor: FluTheme.dark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark
}
onDataSourceChanged: {
tree_model.setDataSource(dataSource)
@ -41,6 +44,7 @@ Item {
signal pooled
onReused: {
console.debug(itemModel.title)
}
onPooled: {
}
@ -83,6 +87,7 @@ Item {
drag.target:control.draggable ? loader_container : undefined
hoverEnabled: true
drag.onActiveChanged: {
d.itemDragActive = drag.active
if(drag.active){
if(itemModel.isExpanded && itemModel.hasChildren()){
tree_model.collapse(rowIndex)
@ -93,6 +98,7 @@ Item {
}
onPressed:
(mouse)=>{
d.itemPress = true
clickPos = Qt.point(mouse.x,mouse.y)
console.debug(clickPos)
loader_container.itemControl = itemControl
@ -100,8 +106,8 @@ Item {
var cellPosition = item_container.mapToItem(table_view, 0, 0)
loader_container.width = item_container.width
loader_container.height = item_container.height
loader_container.x = table_view.contentX + cellPosition.x
loader_container.y = table_view.contentY + cellPosition.y
loader_container.x = cellPosition.x
loader_container.y = cellPosition.y
}
onClicked: {
d.current = itemModel
@ -111,17 +117,21 @@ Item {
item_container.toggle()
}
}
onExited: {
d.hoverIndex = -1
}
onPositionChanged:
(mouse)=> {
if(!drag.active){
return
}
var cellPosition = item_container.mapToItem(table_view, 0, 0)
if(mouse.y+cellPosition.y<0 || mouse.y+cellPosition.y>table_view.height){
d.hoverItem = undefined
d.hoverIndex = -1
d.dropIndex = -1
return
}
if((mouse.x-table_view.contentX)>table_view.width || (mouse.x-table_view.contentX)<0){
d.hoverItem = undefined
d.hoverIndex = -1
d.dropIndex = -1
return
}
@ -129,6 +139,16 @@ Item {
var viewPos = table_view.mapToGlobal(0,0)
var y = table_view.contentY + pos.y-viewPos.y
var index = Math.floor(y/30)
if(item_mouse.pressed){
d.hoverItem = undefined
d.hoverIndex = -1
}else{
d.hoverItem = item_container
d.hoverIndex = index
}
if(!drag.active){
return
}
if(tree_model.hitHasChildrenExpanded(index) && y>index*30+15){
d.dropIndex = index + 1
d.isDropTopArea = true
@ -143,10 +163,12 @@ Item {
}
onCanceled: {
loader_container.sourceComponent = undefined
d.itemPress = false
d.dropIndex = -1
d.dragIndex = -1
}
onReleased: {
d.itemPress = false
loader_container.sourceComponent = undefined
if(d.dropIndex !== -1){
tree_model.dragAnddrop(d.dragIndex,d.dropIndex,d.isDropTopArea)
@ -155,6 +177,7 @@ Item {
d.dragIndex = -1
}
}
Drag.dragType: Drag.None
Drag.active: item_mouse.drag.active
Rectangle{
id:item_line_drop_tip
@ -255,17 +278,11 @@ Item {
if(isCurrent){
return Qt.rgba(1,1,1,0.03)
}
if(item_mouse.containsMouse){
return Qt.rgba(1,1,1,0.03)
}
return Qt.rgba(0,0,0,0)
}else{
if(isCurrent){
return Qt.rgba(0,0,0,0.06)
}
if(item_mouse.containsMouse){
return Qt.rgba(0,0,0,0.03)
}
return Qt.rgba(0,0,0,0)
}
}
@ -275,18 +292,26 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 14 + 30*itemModel.depth
FluIconButton{
Item{
opacity: itemModel.hasChildren()
Layout.preferredWidth: 20
Layout.preferredHeight: 20
enabled: opacity
opacity: itemModel.hasChildren()
contentItem: FluIcon{
TapHandler{
enabled: parent.opacity
onSingleTapped: {
item_container.toggle()
}
}
MouseArea{
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.NoButton
anchors.fill: parent
}
FluIcon{
rotation: itemModel.isExpanded?0:-90
iconSource:FluentIcons.ChevronDown
iconSize: 16
}
onClicked: {
item_container.toggle()
anchors.centerIn: parent
}
}
Item{
@ -299,9 +324,6 @@ Item {
text: itemModel.title
anchors.centerIn: parent
color:{
if(item_mouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
}
}
@ -309,10 +331,65 @@ Item {
}
}
}
Component{
id:com_background
Item{
Rectangle{
radius: 4
anchors{
fill: parent
leftMargin: 6
rightMargin: 6
}
color:{
if(FluTheme.dark){
if(d.itemPress){
return Qt.rgba(1,1,1,0.06)
}
return Qt.rgba(1,1,1,0.03)
}else{
if(d.itemPress){
return Qt.rgba(0,0,0,0.06)
}
return Qt.rgba(0,0,0,0.03)
}
}
}
}
}
ScrollView{
id:scroll_view
anchors.fill: parent
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
Loader{
id:loader_background
y:{
if(d.hoverItem){
var cellPosition = d.hoverItem.mapToItem(table_view, 0, 0)
return cellPosition.y
}
return 0
}
width: {
if(d.hoverItem){
return d.hoverItem.width
}
return 0
}
height: {
if(d.hoverItem){
return d.hoverItem.height
}
return 0
}
sourceComponent: {
if(d.hoverIndex === -1 || d.itemDragActive){
return undefined
}
return com_background
}
}
TableView{
id:table_view
ScrollBar.horizontal: FluScrollBar{}