From a96191b2af42ac01b5d6617f2b474c84448f9375 Mon Sep 17 00:00:00 2001
From: zhuzichu <zhuzichu520@gmail.com>
Date: Thu, 21 Sep 2023 18:29:09 +0800
Subject: [PATCH] update

---
 example/qml-Qt6/page/T_TreeView.qml           |   5 +-
 example/qml/page/T_TreeView.qml               |   4 +-
 src/FluTools.cpp                              |   5 +
 src/FluTools.h                                |   1 +
 src/FluTreeModel.cpp                          | 115 +++++++++----
 .../imports/FluentUI/Controls/FluTreeView.qml |   5 +-
 .../imports/FluentUI/Controls/FluTreeView.qml | 152 ++++++++----------
 7 files changed, 173 insertions(+), 114 deletions(-)

diff --git a/example/qml-Qt6/page/T_TreeView.qml b/example/qml-Qt6/page/T_TreeView.qml
index 2432e528..646827d1 100644
--- a/example/qml-Qt6/page/T_TreeView.qml
+++ b/example/qml-Qt6/page/T_TreeView.qml
@@ -10,9 +10,9 @@ FluScrollablePage {
     title:"TreeView"
 
     function treeData(){
-        const dig = (path = '0', level = 3) => {
+        const dig = (path = '0', level = 4) => {
             const list = [];
-            for (let i = 0; i < 8; i += 1) {
+            for (let i = 0; i < 9; i += 1) {
                 const key = `${path}-${i}`;
                 const treeNode = {
                     title: key,
@@ -130,4 +130,3 @@ FluScrollablePage {
 '
     }
 }
-
diff --git a/example/qml/page/T_TreeView.qml b/example/qml/page/T_TreeView.qml
index 910615f5..54206aff 100644
--- a/example/qml/page/T_TreeView.qml
+++ b/example/qml/page/T_TreeView.qml
@@ -11,9 +11,9 @@ FluScrollablePage {
     title:"TreeView"
 
     function treeData(){
-        const dig = (path = '0', level = 3) => {
+        const dig = (path = '0', level = 4) => {
             const list = [];
-            for (let i = 0; i < 8; i += 1) {
+            for (let i = 0; i < 9; i += 1) {
                 const key = `${path}-${i}`;
                 const treeNode = {
                     title: key,
diff --git a/src/FluTools.cpp b/src/FluTools.cpp
index fee8e81d..8207c867 100644
--- a/src/FluTools.cpp
+++ b/src/FluTools.cpp
@@ -13,6 +13,7 @@
 #include <QCryptographicHash>
 #include <QTextDocument>
 #include <QQuickWindow>
+#include <QDateTime>
 
 FluTools::FluTools(QObject *parent):QObject{parent}{
 
@@ -170,3 +171,7 @@ bool FluTools::isSoftware(){
 QPoint FluTools::cursorPos(){
     return QCursor::pos();
 }
+
+qint64 FluTools::currentTimestamp(){
+    return QDateTime::currentMSecsSinceEpoch();
+}
diff --git a/src/FluTools.h b/src/FluTools.h
index 25fe0ff4..44d2b55c 100644
--- a/src/FluTools.h
+++ b/src/FluTools.h
@@ -47,6 +47,7 @@ public:
     Q_INVOKABLE bool removeFile(QString filePath);
     Q_INVOKABLE void showFileInFolder(QString path);
     Q_INVOKABLE bool isSoftware();
+    Q_INVOKABLE qint64 currentTimestamp();
     Q_INVOKABLE QPoint cursorPos();
 };
 
diff --git a/src/FluTreeModel.cpp b/src/FluTreeModel.cpp
index 8820753c..89ebc001 100644
--- a/src/FluTreeModel.cpp
+++ b/src/FluTreeModel.cpp
@@ -56,9 +56,11 @@ void FluTreeModel::removeRows(int row,int count){
     if (row < 0 || row + count > _rows.size() || count==0)
         return;
     beginRemoveRows(QModelIndex(),row, row + count - 1);
-    for (int i = 0; i < count; ++i) {
-        _rows.removeAt(row);
-    }
+    QList<Node*> firstPart = _rows.mid(0,row);
+    QList<Node*> secondPart = _rows.mid(row + count);
+    _rows.clear();
+    _rows.append(firstPart);
+    _rows.append(secondPart);
     endRemoveRows();
 }
 
@@ -66,9 +68,12 @@ void FluTreeModel::insertRows(int row,QList<Node*> data){
     if (row < 0 || row > _rows.size() || data.size() == 0)
         return;;
     beginInsertRows(QModelIndex(), row, row + data.size() - 1);
-    for (const auto& item : data) {
-        _rows.insert(row++, item);
-    }
+    QList<Node*> firstPart = _rows.mid(0, row);
+    QList<Node*> secondPart = _rows.mid(row);
+    _rows.clear();
+    _rows.append(firstPart);
+    _rows.append(data);
+    _rows.append(secondPart);
     endInsertRows();
 }
 
@@ -84,6 +89,7 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
     }
     _root = new Node(this);
     std::reverse(data.begin(), data.end());
+    auto startTime = QDateTime::currentMSecsSinceEpoch();
     while (data.count() > 0) {
         auto item = data.at(data.count()-1);
         data.pop_back();
@@ -104,8 +110,8 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
             QList<QVariant> children = item.value("children").toList();
             if(!children.isEmpty()){
                 std::reverse(children.begin(), children.end());
-                foreach (auto c, children) {
-                    auto child = c.toMap();
+                for (int i = 0; i < children.count(); ++i) {
+                    auto child = children.at(i).toMap();
                     child.insert("__depth",item.value("__depth").toInt(0)+1);
                     child.insert("__parent",QVariant::fromValue(node));
                     data.append(child);
@@ -113,6 +119,7 @@ void FluTreeModel::setDataSource(QList<QMap<QString,QVariant>> data){
             }
         }
     }
+    auto endTime = QDateTime::currentMSecsSinceEpoch();
     beginResetModel();
     _rows = _dataSource;
     endResetModel();
@@ -170,19 +177,58 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
     }
     auto dragItem = _rows[dragIndex];
     auto dropItem = _rows[dropIndex];
-    if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), dropIndex > dragIndex ? dropIndex+1 : dropIndex)) {
+    int targetIndex;
+    if(dropIndex > dragIndex){
+        if(isDropTopArea){
+            targetIndex = dropIndex;
+        }else{
+            targetIndex = dropIndex+1;
+        }
+    }else{
+        if(isDropTopArea){
+            targetIndex = dropIndex;
+        }else{
+            targetIndex = dropIndex+1;
+        }
+    }
+    if (!beginMoveRows(QModelIndex(), dragIndex, dragIndex, QModelIndex(), targetIndex)) {
         return;
     }
+    if(dropIndex > dragIndex){
+        if(isDropTopArea){
+            targetIndex = dropIndex-1;
+        }else{
+            targetIndex = dropIndex;
+        }
+    }else{
+        if(isDropTopArea){
+            targetIndex = dropIndex;
+        }else{
+            targetIndex = dropIndex+1;
+        }
+    }
+    _rows.move(dragIndex,targetIndex);
+    endMoveRows();
+
+    Q_EMIT layoutAboutToBeChanged();
     if(dragItem->_parent == dropItem->_parent){
         QList<Node*>* children = &(dragItem->_parent->_children);
         int srcIndex = children->indexOf(dragItem);
         int destIndex = children->indexOf(dropItem);
-        int offset = 1;
-        if(isDropTopArea){
-            offset = offset - 1;
+        if(dropIndex > dragIndex){
+            if(isDropTopArea){
+                targetIndex = destIndex-1;
+            }else{
+                targetIndex = destIndex;
+            }
+        }else{
+            if(isDropTopArea){
+                targetIndex = destIndex;
+            }else{
+                targetIndex = destIndex+1;
+            }
         }
-        children->move(srcIndex,destIndex>srcIndex? destIndex-1 + offset : destIndex + offset);
-        _rows.move(dragIndex,dropIndex>dragIndex? dropIndex-1 + offset : dropIndex + offset);
+        children->move(srcIndex,targetIndex);
     }else{
         QList<Node*>* srcChildren = &(dragItem->_parent->_children);
         QList<Node*>* destChildren = &(dropItem->_parent->_children);
@@ -210,25 +256,40 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
             }
         }
         srcChildren->removeAt(srcIndex);
-        int offset = 0;
-        if(!isDropTopArea){
-            offset =  offset + 1;
+
+        if(dropIndex > dragIndex){
+            if(isDropTopArea){
+                targetIndex = destIndex;
+            }else{
+                targetIndex = destIndex + 1;
+            }
+        }else{
+            if(isDropTopArea){
+                targetIndex = destIndex;
+            }else{
+                targetIndex = destIndex + 1;
+            }
         }
-        destChildren->insert(destIndex+offset,dragItem);
-        offset = 1;
-        if(isDropTopArea){
-            offset = offset - 1;
+
+        destChildren->insert(targetIndex,dragItem);
+
+        foreach (auto item,*destChildren) {
+            qDebug()<<item->title();
         }
-        _rows.move(dragIndex,dropIndex>dragIndex? dropIndex-1+offset : dropIndex+offset);
+
     }
-    endMoveRows();
+
+    changePersistentIndex(index(qMin(dragIndex,dropIndex),0),index(qMax(dragIndex,dropIndex),0));
+
+    Q_EMIT layoutChanged(QList<QPersistentModelIndex>(),QAbstractItemModel::VerticalSortHint);
+
 }
 
 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;
 }
 
diff --git a/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml b/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml
index 4343c747..51fbad6d 100644
--- a/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml
+++ b/src/Qt5/imports/FluentUI/Controls/FluTreeView.qml
@@ -54,6 +54,9 @@ Item {
                 }
             }
         }
+        move: Transition {
+            NumberAnimation { property: "y"; duration: 200 }
+        }
         add: Transition{
             ParallelAnimation{
                 NumberAnimation {
@@ -164,7 +167,7 @@ Item {
                         loader_container.width = item_container.width
                         loader_container.height = item_container.height
                         loader_container.x = 0
-                        loader_container.y = cellPosition.y + table_view.contentY
+                        loader_container.y = cellPosition.y
                     }
                 onClicked: {
                     d.current = itemModel
diff --git a/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml b/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml
index 1d62765f..3da6f21c 100644
--- a/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml
+++ b/src/Qt6/imports/FluentUI/Controls/FluTreeView.qml
@@ -27,11 +27,76 @@ Item {
     FluTreeModel{
         id:tree_model
     }
-    Timer{
-        id:timer_refresh
-        interval: 10
-        onTriggered: {
-            table_view.forceLayout()
+    ListView{
+        id:table_view
+        ScrollBar.horizontal: FluScrollBar{}
+        ScrollBar.vertical: FluScrollBar{}
+        boundsBehavior: Flickable.StopAtBounds
+        model: tree_model
+        anchors.fill: parent
+        clip: true
+        flickableDirection: Flickable.HorizontalAndVerticalFlick
+        contentWidth: contentItem.childrenRect.width
+        reuseItems: true
+        removeDisplaced : Transition{
+            ParallelAnimation{
+                NumberAnimation {
+                    properties: "y"
+                    duration: 167
+                    from: d.dy + table_view.height
+                    easing.type: Easing.OutCubic
+                }
+                NumberAnimation {
+                    properties: "opacity"
+                    duration: 300
+                    from: 0
+                    to: 1
+                }
+            }
+        }
+        move: Transition {
+            NumberAnimation { property: "y"; duration: 200 }
+        }
+        add: Transition{
+            ParallelAnimation{
+                NumberAnimation {
+                    properties: "y"
+                    duration: 167
+                    from: d.dy
+                    easing.type: Easing.OutCubic
+                }
+                NumberAnimation {
+                    properties: "opacity"
+                    duration: 300
+                    from: 0
+                    to: 1
+                }
+            }
+        }
+        delegate: Item {
+            id:item_control
+            implicitWidth: item_loader_container.width
+            implicitHeight: item_loader_container.height
+            ListView.onReused: {
+                item_loader_container.item.reused()
+            }
+            ListView.onPooled: {
+                item_loader_container.item.pooled()
+            }
+            Loader{
+                property var itemControl: item_control
+                property var itemModel: modelData
+                property int rowIndex: index
+                property bool isItemLoader: true
+                id:item_loader_container
+                sourceComponent: com_item_container
+            }
+        }
+        Loader{
+            id:loader_container
+            property var itemControl
+            property var itemModel
+            property bool isItemLoader: false
         }
     }
     Component{
@@ -102,7 +167,7 @@ Item {
                         loader_container.width = item_container.width
                         loader_container.height = item_container.height
                         loader_container.x = 0
-                        loader_container.y = cellPosition.y + table_view.contentY
+                        loader_container.y = cellPosition.y
                     }
                 onClicked: {
                     d.current = itemModel
@@ -320,81 +385,6 @@ Item {
             }
         }
     }
-    ScrollView{
-        id:scroll_view
-        anchors.fill: parent
-        ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
-        ScrollBar.vertical.policy: ScrollBar.AlwaysOff
-            clip: true
-        ListView{
-            id:table_view
-            ScrollBar.horizontal: FluScrollBar{}
-            ScrollBar.vertical: FluScrollBar{}
-            boundsBehavior: Flickable.StopAtBounds
-            model: tree_model
-            clip: true
-            anchors.fill: parent
-            contentWidth: contentItem.childrenRect.width
-            reuseItems: true
-            removeDisplaced : Transition{
-                ParallelAnimation{
-                    NumberAnimation {
-                        properties: "y"
-                        duration: 167
-                        from: d.dy + table_view.height
-                        easing.type: Easing.OutCubic
-                    }
-                    NumberAnimation {
-                        properties: "opacity"
-                        duration: 300
-                        from: 0
-                        to: 1
-                    }
-                }
-            }
-            add: Transition{
-                ParallelAnimation{
-                    NumberAnimation {
-                        properties: "y"
-                        duration: 167
-                        from: d.dy
-                        easing.type: Easing.OutCubic
-                    }
-                    NumberAnimation {
-                        properties: "opacity"
-                        duration: 300
-                        from: 0
-                        to: 1
-                    }
-                }
-            }
-            delegate: Item {
-                id:item_control
-                implicitWidth: item_loader_container.width
-                implicitHeight: item_loader_container.height
-                ListView.onReused: {
-                    item_loader_container.item.reused()
-                }
-                ListView.onPooled: {
-                    item_loader_container.item.pooled()
-                }
-                Loader{
-                    property var itemControl: item_control
-                    property var itemModel: modelData
-                    property int rowIndex: index
-                    property bool isItemLoader: true
-                    id:item_loader_container
-                    sourceComponent: com_item_container
-                }
-            }
-        }
-        Loader{
-            id:loader_container
-            property var itemControl
-            property var itemModel
-            property bool isItemLoader: false
-        }
-    }
     function count(){
         return tree_model.dataSourceSize
     }