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 #include #include +#include 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 firstPart = _rows.mid(0,row); + QList secondPart = _rows.mid(row + count); + _rows.clear(); + _rows.append(firstPart); + _rows.append(secondPart); endRemoveRows(); } @@ -66,9 +68,12 @@ void FluTreeModel::insertRows(int row,QList 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 firstPart = _rows.mid(0, row); + QList secondPart = _rows.mid(row); + _rows.clear(); + _rows.append(firstPart); + _rows.append(data); + _rows.append(secondPart); endInsertRows(); } @@ -84,6 +89,7 @@ void FluTreeModel::setDataSource(QList> 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> data){ QList 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> 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* 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* srcChildren = &(dragItem->_parent->_children); QList* 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()<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(),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 }