This commit is contained in:
朱子楚\zhuzi 2023-09-22 00:11:58 +08:00
parent a96191b2af
commit 77d9b4bde9
8 changed files with 263 additions and 262 deletions

View File

@ -5,7 +5,7 @@ import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage {
FluContentPage {
title:"TreeView"
@ -28,67 +28,47 @@ FluScrollablePage {
return dig();
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 80
Column{
anchors.verticalCenter: parent.verticalCenter
id:layout_column
spacing: 12
width: 300
anchors{
topMargin: 20
top:parent.top
left: parent.left
leftMargin: 10
bottom:parent.bottom
bottomMargin: 20
}
FluText{
text:"共计%1条数据当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
}
RowLayout{
spacing: 10
FluText{
text:"高性能树控件新的TreeView用TableView实现"
text:"cellHeight:"
Layout.alignment: Qt.AlignVCenter
}
FluText{
text:"共计:%1条数据当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
FluSlider{
id:slider_cell_height
value: 30
from: 30
to:100
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 420
Item{
anchors.fill: tree_view
FluShadow{}
}
FluTreeView{
id:tree_view
width:slider_width.value
anchors{
top:parent.top
left:parent.left
bottom:parent.bottom
}
draggable:switch_draggable.checked
showLine: switch_showline.checked
Component.onCompleted: {
var data = treeData()
dataSource = data
}
}
Column{
spacing: 15
anchors{
top:parent.top
topMargin: 10
bottomMargin: 10
rightMargin: 10
bottom:parent.bottom
right: parent.right
}
RowLayout{
spacing: 10
FluText{
text:"width:"
text:"depthPadding:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_width
value: 280
from: 160
to:400
id:slider_depth_padding
value: 30
from: 30
to:100
}
}
FluToggleSwitch{
@ -114,19 +94,28 @@ FluScrollablePage {
}
}
}
FluArea{
anchors{
left: layout_column.right
top: parent.top
bottom: parent.bottom
right: parent.right
rightMargin: 5
topMargin: 5
bottomMargin: 5
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluTreeView{
FluShadow{}
FluTreeView{
id:tree_view
width:240
height:600
anchors.fill: parent
cellHeight: slider_cell_height.value
draggable:switch_draggable.checked
showLine: switch_showline.checked
depthPadding: slider_depth_padding.value
Component.onCompleted: {
var data = treeData()
dataSource = data
}
}
'
}
}
}

View File

@ -183,7 +183,7 @@ CustomWindow {
z:999
//StackpopFluPagelaunchMode
// pageMode: FluNavigationViewType.Stack
//NoStack
//NoStackFluViewModel
pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal
footerItems:ItemsFooter

View File

@ -6,7 +6,7 @@ import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage {
FluContentPage {
title:"TreeView"
@ -29,67 +29,47 @@ FluScrollablePage {
return dig();
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 80
Column{
anchors.verticalCenter: parent.verticalCenter
id:layout_column
spacing: 12
width: 300
anchors{
topMargin: 20
top:parent.top
left: parent.left
leftMargin: 10
bottom:parent.bottom
bottomMargin: 20
}
FluText{
text:"共计%1条数据当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
}
RowLayout{
spacing: 10
FluText{
text:"高性能树控件新的TreeView用TableView实现"
text:"cellHeight:"
Layout.alignment: Qt.AlignVCenter
}
FluText{
text:"共计:%1条数据当前显示的%2条数据".arg(tree_view.count()).arg(tree_view.visibleCount())
FluSlider{
id:slider_cell_height
value: 30
from: 30
to:100
}
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 10
paddings: 10
height: 420
Item{
anchors.fill: tree_view
FluShadow{}
}
FluTreeView{
id:tree_view
width:slider_width.value
anchors{
top:parent.top
left:parent.left
bottom:parent.bottom
}
draggable:switch_draggable.checked
showLine: switch_showline.checked
Component.onCompleted: {
var data = treeData()
dataSource = data
}
}
Column{
spacing: 15
anchors{
top:parent.top
topMargin: 10
bottomMargin: 10
rightMargin: 10
bottom:parent.bottom
right: parent.right
}
RowLayout{
spacing: 10
FluText{
text:"width:"
text:"depthPadding:"
Layout.alignment: Qt.AlignVCenter
}
FluSlider{
id:slider_width
value: 280
from: 160
to:400
id:slider_depth_padding
value: 30
from: 30
to:100
}
}
FluToggleSwitch{
@ -115,19 +95,28 @@ FluScrollablePage {
}
}
}
FluArea{
anchors{
left: layout_column.right
top: parent.top
bottom: parent.bottom
right: parent.right
rightMargin: 5
topMargin: 5
bottomMargin: 5
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluTreeView{
FluShadow{}
FluTreeView{
id:tree_view
width:240
height:600
anchors.fill: parent
cellHeight: slider_cell_height.value
draggable:switch_draggable.checked
showLine: switch_showline.checked
depthPadding: slider_depth_padding.value
Component.onCompleted: {
var data = treeData()
dataSource = data
}
}
'
}
}
}

View File

@ -186,7 +186,7 @@ CustomWindow {
z:999
//StackpopFluPagelaunchMode
// pageMode: FluNavigationViewType.Stack
//NoStack
//NoStackFluViewModel
pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal
footerItems:ItemsFooter

View File

@ -119,7 +119,8 @@ void FluHttp::post(HttpRequest* r,HttpCallable* c){
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError;
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
@ -134,6 +135,9 @@ void FluHttp::post(HttpRequest* r,HttpCallable* c){
onError(callable,status,errorString,result);
}
}
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
@ -174,7 +178,8 @@ void FluHttp::postString(HttpRequest* r,HttpCallable* c){
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError;
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
@ -189,6 +194,9 @@ void FluHttp::postString(HttpRequest* r,HttpCallable* c){
onError(callable,status,errorString,result);
}
}
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
@ -228,7 +236,8 @@ void FluHttp::postJson(HttpRequest* r,HttpCallable* c){
QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError;
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
reply->deleteLater();
reply = nullptr;
if (isSuccess) {
@ -243,6 +252,9 @@ void FluHttp::postJson(HttpRequest* r,HttpCallable* c){
onError(callable,status,errorString,result);
}
}
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});
@ -273,14 +285,15 @@ void FluHttp::get(HttpRequest* r,HttpCallable* c){
QNetworkRequest req(url);
addHeaders(&req,data["headers"].toMap());
QEventLoop loop;
QNetworkReply* reply = manager.get(req);
auto reply = QPointer(manager.get(req));
_cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,&manager,[&loop](QNetworkReply *reply){loop.quit();});
connect(qApp,&QGuiApplication::aboutToQuit,&manager, [&loop](){loop.quit();});
loop.exec();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError;
QNetworkReply::NetworkError error = reply->error();
bool isSuccess = error == QNetworkReply::NoError;
QString result = QString::fromUtf8(reply->readAll());
if (isSuccess) {
handleCache(httpId,result);
@ -296,6 +309,9 @@ void FluHttp::get(HttpRequest* r,HttpCallable* c){
}
reply->deleteLater();
reply = nullptr;
if(error == QNetworkReply::OperationCanceledError){
break;
}
}
onFinish(callable,request);
});

View File

@ -2,15 +2,10 @@
#include <QMetaEnum>
Node::Node(QObject *parent)
: QObject{parent}
{
Node::Node(QObject *parent): QObject{parent}{
}
FluTreeModel::FluTreeModel(QObject *parent)
: QAbstractItemModel{parent}
{
FluTreeModel::FluTreeModel(QObject *parent): QAbstractItemModel{parent}{
dataSourceSize(0);
}
@ -209,7 +204,6 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
}
_rows.move(dragIndex,targetIndex);
endMoveRows();
Q_EMIT layoutAboutToBeChanged();
if(dragItem->_parent == dropItem->_parent){
QList<Node*>* children = &(dragItem->_parent->_children);
@ -256,7 +250,6 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
}
}
srcChildren->removeAt(srcIndex);
if(dropIndex > dragIndex){
if(isDropTopArea){
targetIndex = destIndex;
@ -270,26 +263,18 @@ void FluTreeModel::dragAnddrop(int dragIndex,int dropIndex,bool isDropTopArea){
targetIndex = destIndex + 1;
}
}
destChildren->insert(targetIndex,dragItem);
foreach (auto item,*destChildren) {
qDebug()<<item->title();
}
}
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;
}

View File

@ -10,6 +10,8 @@ Item {
property var dataSource
property bool showLine: true
property bool draggable: false
property int cellHeight: 30
property int depthPadding: 30
property color lineColor: FluTheme.dark ? Qt.rgba(111/255,111/255,111/255,1) : Qt.rgba(217/255,217/255,217/255,1)
id:control
QtObject {
@ -112,13 +114,13 @@ Item {
property bool isCurrent: d.current === itemModel
id:item_container
width: {
var w = 46 + item_layout_text.width + 30*itemModel.depth
var w = 46 + item_loader_cell.width + control.depthPadding*itemModel.depth
if(control.width>w){
return control.width
}
return w
}
height: 30
height: control.cellHeight
implicitWidth: width
implicitHeight: height
function toggle(){
@ -194,13 +196,13 @@ Item {
var pos = FluTools.cursorPos()
var viewPos = table_view.mapToGlobal(0,0)
var y = table_view.contentY + pos.y-viewPos.y
var index = Math.floor(y/30)
if(tree_model.hitHasChildrenExpanded(index) && y>index*30+15){
var index = Math.floor(y/control.cellHeight)
if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){
d.dropIndex = index + 1
d.isDropTopArea = true
}else{
d.dropIndex = index
if(y>index*30+15){
if(y>index*control.cellHeight+control.cellHeight/2){
d.isDropTopArea = false
}else{
d.isDropTopArea = true
@ -229,14 +231,8 @@ Item {
Rectangle{
id:item_line_drop_tip
anchors{
left: parent.left
leftMargin: {
var count = itemModel.depth+1
if(itemModel.hasChildren()){
return 30*count - 8
}
return 30*count + 18
}
left: layout_row.left
leftMargin: 26
right: parent.right
rightMargin: 10
bottom: parent.bottom
@ -283,18 +279,18 @@ Item {
height: itemModel.hideLineFooter() ? parent.height/2 : parent.height
anchors{
top: parent.top
right: layout_row.left
rightMargin: -9
left: item_line_h.left
}
}
FluRectangle{
id:item_line_h
height: 1
color: control.lineColor
visible: control.showLine && isItemLoader && itemModel.depth !== 0 && !itemModel.hasChildren()
width: 18
width: depthPadding - 10
anchors{
right: layout_row.left
rightMargin: -27
rightMargin: -24
verticalCenter: parent.verticalCenter
}
}
@ -309,7 +305,7 @@ Item {
top:parent.top
bottom: parent.bottom
left: parent.left
leftMargin: 30*(index+2) - 8
leftMargin: control.depthPadding*(index+1) + 24
}
}
}
@ -342,9 +338,10 @@ Item {
}
RowLayout{
id:layout_row
height: parent.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 14 + 30*itemModel.depth
anchors.leftMargin: 14 + control.depthPadding*itemModel.depth
Component{
id:com_icon_btn
FluIconButton{
@ -364,18 +361,35 @@ Item {
Layout.preferredWidth: 20
Layout.preferredHeight: 20
sourceComponent: itemModel.hasChildren() ? com_icon_btn : undefined
}
Item{
id:item_layout_text
Layout.preferredWidth: item_text.implicitWidth+14
Layout.preferredHeight:item_text.implicitHeight+14
Layout.alignment: Qt.AlignVCenter
}
Loader{
property var modelData: itemModel
property var itemMouse: item_mouse
id:item_loader_cell
Layout.preferredWidth: {
if(item){
return item.width
}
return 0
}
Layout.fillHeight: true
sourceComponent:com_item_text
}
}
}
}
Component{
id:com_item_text
Item{
width: item_text.width
FluText {
id:item_text
text: itemModel.title
text: modelData.title
rightPadding: 14
anchors.centerIn: parent
color:{
if(item_mouse.pressed){
if(itemMouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
@ -383,8 +397,6 @@ Item {
}
}
}
}
}
function count(){
return tree_model.dataSourceSize
}
@ -403,5 +415,4 @@ Item {
function allCollapse(){
tree_model.allCollapse()
}
}

View File

@ -10,6 +10,8 @@ Item {
property var dataSource
property bool showLine: true
property bool draggable: false
property int cellHeight: 30
property int depthPadding: 30
property color lineColor: FluTheme.dark ? Qt.rgba(111/255,111/255,111/255,1) : Qt.rgba(217/255,217/255,217/255,1)
id:control
QtObject {
@ -112,13 +114,13 @@ Item {
property bool isCurrent: d.current === itemModel
id:item_container
width: {
var w = 46 + item_layout_text.width + 30*itemModel.depth
var w = 46 + item_loader_cell.width + control.depthPadding*itemModel.depth
if(control.width>w){
return control.width
}
return w
}
height: 30
height: control.cellHeight
implicitWidth: width
implicitHeight: height
function toggle(){
@ -194,13 +196,13 @@ Item {
var pos = FluTools.cursorPos()
var viewPos = table_view.mapToGlobal(0,0)
var y = table_view.contentY + pos.y-viewPos.y
var index = Math.floor(y/30)
if(tree_model.hitHasChildrenExpanded(index) && y>index*30+15){
var index = Math.floor(y/control.cellHeight)
if(tree_model.hitHasChildrenExpanded(index) && y>index*control.cellHeight+control.cellHeight/2){
d.dropIndex = index + 1
d.isDropTopArea = true
}else{
d.dropIndex = index
if(y>index*30+15){
if(y>index*control.cellHeight+control.cellHeight/2){
d.isDropTopArea = false
}else{
d.isDropTopArea = true
@ -229,14 +231,8 @@ Item {
Rectangle{
id:item_line_drop_tip
anchors{
left: parent.left
leftMargin: {
var count = itemModel.depth+1
if(itemModel.hasChildren()){
return 30*count - 8
}
return 30*count + 18
}
left: layout_row.left
leftMargin: 26
right: parent.right
rightMargin: 10
bottom: parent.bottom
@ -283,18 +279,18 @@ Item {
height: itemModel.hideLineFooter() ? parent.height/2 : parent.height
anchors{
top: parent.top
right: layout_row.left
rightMargin: -9
left: item_line_h.left
}
}
FluRectangle{
id:item_line_h
height: 1
color: control.lineColor
visible: control.showLine && isItemLoader && itemModel.depth !== 0 && !itemModel.hasChildren()
width: 18
width: depthPadding - 10
anchors{
right: layout_row.left
rightMargin: -27
rightMargin: -24
verticalCenter: parent.verticalCenter
}
}
@ -309,7 +305,7 @@ Item {
top:parent.top
bottom: parent.bottom
left: parent.left
leftMargin: 30*(index+2) - 8
leftMargin: control.depthPadding*(index+1) + 24
}
}
}
@ -342,9 +338,10 @@ Item {
}
RowLayout{
id:layout_row
height: parent.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 14 + 30*itemModel.depth
anchors.leftMargin: 14 + control.depthPadding*itemModel.depth
Component{
id:com_icon_btn
FluIconButton{
@ -364,18 +361,35 @@ Item {
Layout.preferredWidth: 20
Layout.preferredHeight: 20
sourceComponent: itemModel.hasChildren() ? com_icon_btn : undefined
}
Item{
id:item_layout_text
Layout.preferredWidth: item_text.implicitWidth+14
Layout.preferredHeight:item_text.implicitHeight+14
Layout.alignment: Qt.AlignVCenter
}
Loader{
property var modelData: itemModel
property var itemMouse: item_mouse
id:item_loader_cell
Layout.preferredWidth: {
if(item){
return item.width
}
return 0
}
Layout.fillHeight: true
sourceComponent:com_item_text
}
}
}
}
Component{
id:com_item_text
Item{
width: item_text.width
FluText {
id:item_text
text: itemModel.title
text: modelData.title
rightPadding: 14
anchors.centerIn: parent
color:{
if(item_mouse.pressed){
if(itemMouse.pressed){
return FluTheme.dark ? FluColors.Grey80 : FluColors.Grey120
}
return FluTheme.dark ? FluColors.White : FluColors.Grey220
@ -383,8 +397,6 @@ Item {
}
}
}
}
}
function count(){
return tree_model.dataSourceSize
}
@ -403,5 +415,4 @@ Item {
function allCollapse(){
tree_model.allCollapse()
}
}