update
parent
73bf9576d4
commit
8412d1fa04
|
@ -12,181 +12,44 @@ Item {
|
|||
fontStyle: FluText.TitleLarge
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: tree_model
|
||||
ListElement {
|
||||
text: "Root"
|
||||
expanded:true
|
||||
items: [
|
||||
ListElement {
|
||||
text: "Node 1"
|
||||
expanded:false
|
||||
items: [
|
||||
ListElement {
|
||||
text: "Node 1.1"
|
||||
expanded:true
|
||||
items:[
|
||||
ListElement{
|
||||
text:"Node 1.1.1"
|
||||
expanded:true
|
||||
items:[
|
||||
ListElement{
|
||||
text:"Node 1.1.1.1"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.3"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.4"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.5"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.6"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 1.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3"
|
||||
expanded:true
|
||||
items: [
|
||||
ListElement {
|
||||
text: "Node 3.1"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.3"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.4"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.5"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.6"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.7"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.8"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.9"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.10"
|
||||
expanded:true
|
||||
items:[
|
||||
ListElement{
|
||||
text:"Node 3.10.1"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.3"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.4"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.5"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.6"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.7"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.8"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.9"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.11"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
function randomName() {
|
||||
var names = ["张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"]
|
||||
return names[Math.floor(Math.random() * names.length)]
|
||||
}
|
||||
|
||||
function randomCompany() {
|
||||
var companies = ["阿里巴巴", "腾讯", "百度", "京东", "华为", "小米", "字节跳动", "美团", "滴滴"]
|
||||
return companies[Math.floor(Math.random() * companies.length)]
|
||||
}
|
||||
|
||||
function randomDepartment() {
|
||||
var departments = ["技术部", "销售部", "市场部", "人事部", "财务部", "客服部", "产品部", "设计部", "运营部"]
|
||||
return departments[Math.floor(Math.random() * departments.length)]
|
||||
}
|
||||
|
||||
function createEmployee() {
|
||||
var name = randomName()
|
||||
return tree_view.createItem(name, false)
|
||||
}
|
||||
|
||||
function createSubtree(numEmployees) {
|
||||
var employees = []
|
||||
for (var i = 0; i < numEmployees; i++) {
|
||||
employees.push(createEmployee())
|
||||
}
|
||||
return tree_view.createItem(randomDepartment(), true, employees)
|
||||
}
|
||||
|
||||
function createOrg(numLevels, numSubtrees, numEmployees) {
|
||||
if (numLevels === 0) {
|
||||
return []
|
||||
}
|
||||
var subtrees = []
|
||||
for (var i = 0; i < numSubtrees; i++) {
|
||||
subtrees.push(createSubtree(numEmployees))
|
||||
}
|
||||
return [tree_view.createItem(randomCompany(), true, subtrees)].concat(createOrg(numLevels - 1, numSubtrees, numEmployees))
|
||||
}
|
||||
|
||||
|
||||
FluTreeView{
|
||||
|
@ -197,7 +60,17 @@ Item {
|
|||
left:parent.left
|
||||
bottom:parent.bottom
|
||||
}
|
||||
model:tree_model
|
||||
onItemClicked:
|
||||
(model)=>{
|
||||
showSuccess(model.text)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
var org = createOrg(10, 3, 5)
|
||||
updateData(org)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,11 +80,62 @@ Item {
|
|||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
FluButton{
|
||||
text:"test"
|
||||
onClicked: {
|
||||
|
||||
FluText{
|
||||
text:{
|
||||
if(tree_view.selectionMode === FluTreeView.None){
|
||||
return "FluTreeView.None"
|
||||
}
|
||||
if(tree_view.selectionMode === FluTreeView.Single){
|
||||
return "FluTreeView.Single"
|
||||
}
|
||||
if(tree_view.selectionMode === FluTreeView.Multiple){
|
||||
return "FluTreeView.Multiple"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text:"None"
|
||||
onClicked: {
|
||||
tree_view.selectionMode = FluTreeView.None
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text:"Single"
|
||||
onClicked: {
|
||||
tree_view.selectionMode = FluTreeView.Single
|
||||
}
|
||||
}
|
||||
|
||||
FluButton{
|
||||
text:"Multiple"
|
||||
onClicked: {
|
||||
tree_view.selectionMode = FluTreeView.Multiple
|
||||
}
|
||||
}
|
||||
|
||||
FluFilledButton{
|
||||
text:"获取选中的数据"
|
||||
onClicked: {
|
||||
if(tree_view.selectionMode === FluTreeView.None){
|
||||
showError("当前非选择模式,没有选中的数据")
|
||||
}
|
||||
if(tree_view.selectionMode === FluTreeView.Single){
|
||||
showSuccess(tree_view.signleData().text)
|
||||
}
|
||||
if(tree_view.selectionMode === FluTreeView.Multiple){
|
||||
if(tree_view.multipData().length===0){
|
||||
showError("没有选中数据")
|
||||
return
|
||||
}
|
||||
var info = []
|
||||
tree_view.multipData().map((value)=>info.push(value.text))
|
||||
showSuccess(info.join(","))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ Item {
|
|||
id:root
|
||||
property bool checked: false
|
||||
property string text: "Check Box"
|
||||
property var checkClicked
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
|
||||
|
@ -78,6 +79,10 @@ Item {
|
|||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
if(checkClicked){
|
||||
checkClicked()
|
||||
return
|
||||
}
|
||||
checked = !checked
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,263 +9,247 @@ Rectangle {
|
|||
id:root
|
||||
color: FluTheme.isDark ? Qt.rgba(50/255,50/255,50/255,1) : Qt.rgba(253/255,253/255,253/255,1)
|
||||
|
||||
property alias model: list_root.model
|
||||
|
||||
ListModel {
|
||||
id: tree_model
|
||||
ListElement {
|
||||
text: "Root"
|
||||
expanded:true
|
||||
items: [
|
||||
ListElement {
|
||||
text: "Node 1"
|
||||
expanded:false
|
||||
items: [
|
||||
ListElement {
|
||||
text: "Node 1.1"
|
||||
expanded:true
|
||||
items:[
|
||||
ListElement{
|
||||
text:"Node 1.1.1"
|
||||
expanded:true
|
||||
items:[
|
||||
ListElement{
|
||||
text:"Node 1.1.1.1"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.3"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.4"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.5"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 1.1.1.6"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 1.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3"
|
||||
expanded:true
|
||||
items: [
|
||||
ListElement {
|
||||
text: "Node 3.1"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.3"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.4"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.5"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.6"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.7"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.8"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.9"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.10"
|
||||
expanded:true
|
||||
items:[
|
||||
ListElement{
|
||||
text:"Node 3.10.1"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.2"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.3"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.4"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.5"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.6"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.7"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.8"
|
||||
expanded:false
|
||||
items:[]
|
||||
},
|
||||
ListElement{
|
||||
text:"Node 3.10.9"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
},
|
||||
ListElement {
|
||||
text: "Node 3.11"
|
||||
expanded:false
|
||||
items:[]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
enum TreeViewSelectionMode {
|
||||
None,
|
||||
Single,
|
||||
Multiple
|
||||
}
|
||||
|
||||
property int selectionMode: FluTreeView.None
|
||||
|
||||
property var currentElement
|
||||
property var currentParentElement
|
||||
|
||||
property var multipElement: []
|
||||
|
||||
property var rootModel: tree_model.get(0).items
|
||||
|
||||
signal itemClicked(var item)
|
||||
|
||||
ListModel{
|
||||
id:tree_model
|
||||
ListElement{
|
||||
text: "根节点"
|
||||
expanded:true
|
||||
items:[]
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:comp_delegate
|
||||
|
||||
ColumnLayout{
|
||||
id:layout_column
|
||||
spacing: 0
|
||||
id: delegate_root
|
||||
Column{
|
||||
width: calculateWidth()
|
||||
property var itemModel: model
|
||||
property int level: mapToItem(list_root,0,0).x/0.001
|
||||
width: list_root.width
|
||||
Repeater{
|
||||
id: repeater_first_level
|
||||
model: items
|
||||
delegate: delegate_items
|
||||
}
|
||||
function calculateWidth(){
|
||||
var w = 0;
|
||||
for(var i = 0; i < repeater_first_level.count; i++) {
|
||||
var child = repeater_first_level.itemAt(i)
|
||||
if(w < child.width_hint){
|
||||
w = child.width_hint;
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component{
|
||||
id:delegate_items
|
||||
|
||||
Column{
|
||||
id:item_layout
|
||||
|
||||
property real level: (mapToItem(list_root,0,0).x+list_root.contentX)/0.001
|
||||
property var text: model.text??"Item"
|
||||
property bool isItems : (model.items !== undefined) && (model.items.count !== 0)
|
||||
property var items: model.items??[]
|
||||
property var expanded: model.expanded??true
|
||||
property int width_hint: calculateWidth()
|
||||
property bool singleSelected: currentElement === model
|
||||
property var itemModel: model
|
||||
|
||||
function calculateWidth(){
|
||||
var w = Math.max(list_root.width, item_layout_row.implicitWidth + 10);
|
||||
if(expanded){
|
||||
for(var i = 0; i < repeater_items.count; i++) {
|
||||
var child = repeater_items.itemAt(i)
|
||||
if(w < child.width_hint){
|
||||
w = child.width_hint;
|
||||
}
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
Item{
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
Layout.preferredWidth: childrenRect.width
|
||||
id:item_layout_rect
|
||||
width: list_root.contentWidth
|
||||
height: item_layout_row.implicitHeight
|
||||
|
||||
|
||||
Rectangle{
|
||||
height: parent.height
|
||||
width: list_root.width
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2
|
||||
radius: 4
|
||||
color:{
|
||||
if(FluTheme.isDark){
|
||||
if(item_layout.singleSelected && selectionMode === FluTreeView.Single){
|
||||
return Qt.rgba(62/255,62/255,62/255,1)
|
||||
}
|
||||
return (item_layout_mouse.containsMouse || item_layout_expanded.hovered)?Qt.rgba(62/255,62/255,62/255,1):Qt.rgba(50/255,50/255,50/255,1)
|
||||
}else{
|
||||
if(item_layout.singleSelected && selectionMode === FluTreeView.Single){
|
||||
return Qt.rgba(244/255,244/255,244/255,1)
|
||||
}
|
||||
return (item_layout_mouse.containsMouse || item_layout_expanded.hovered)?Qt.rgba(244/255,244/255,244/255,1):Qt.rgba(253/255,253/255,253/255,1)
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle{
|
||||
width: 3
|
||||
color:FluTheme.primaryColor.dark
|
||||
visible: item_layout.singleSelected && (selectionMode === FluTreeView.Single)
|
||||
radius: 3
|
||||
height: 20
|
||||
anchors{
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea{
|
||||
id:item_layout_mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
console.debug("---------")
|
||||
item_layout_rect.onClickItem()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onClickItem(){
|
||||
if(selectionMode === FluTreeView.None){
|
||||
itemClicked(model)
|
||||
}
|
||||
if(selectionMode === FluTreeView.Single){
|
||||
currentElement = model
|
||||
if(item_layout.parent.parent.parent.itemModel){
|
||||
currentParentElement = item_layout.parent.parent.parent.itemModel
|
||||
}else{
|
||||
if(item_layout.parent.itemModel){
|
||||
currentParentElement = item_layout.parent.itemModel
|
||||
}
|
||||
}
|
||||
}
|
||||
if(selectionMode === FluTreeView.Multiple){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout{
|
||||
spacing: 0
|
||||
id:item_layout_row
|
||||
anchors.verticalCenter: item_layout_rect.verticalCenter
|
||||
|
||||
Item{
|
||||
width: 15*level
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
FluCheckBox{
|
||||
text:""
|
||||
checked: multipElement.includes(itemModel)
|
||||
visible: selectionMode === FluTreeView.Multiple
|
||||
checkClicked:function(){
|
||||
if(checked){
|
||||
multipElement = multipElement.filter((value) => value !== itemModel)
|
||||
}else{
|
||||
multipElement = [...multipElement,itemModel]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluIconButton{
|
||||
id:item_layout_expanded
|
||||
color:"#00000000"
|
||||
icon:model.expanded?FluentIcons.FA_angle_down:FluentIcons.FA_angle_right
|
||||
icon:item_layout.expanded?FluentIcons.FA_angle_down:FluentIcons.FA_angle_right
|
||||
opacity: item_layout.isItems
|
||||
onClicked: {
|
||||
if(!item_layout.isItems){
|
||||
item_layout_rect.onClickItem()
|
||||
return
|
||||
}
|
||||
model.expanded = !model.expanded
|
||||
}
|
||||
}
|
||||
FluText{
|
||||
text:model.text
|
||||
|
||||
FluText {
|
||||
text: item_layout.text
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
topPadding: 10
|
||||
bottomPadding: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item{
|
||||
Layout.preferredWidth: layout_column.width
|
||||
Layout.preferredHeight:childrenRect.height
|
||||
visible: model.expanded
|
||||
ListView{
|
||||
id:item_sub
|
||||
visible: {
|
||||
if(!isItems){
|
||||
return false
|
||||
}
|
||||
return item_layout.expanded??false
|
||||
}
|
||||
|
||||
width: item_sub_layout.implicitWidth
|
||||
height: item_sub_layout.implicitHeight
|
||||
x:0.001
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
model:itemModel.items
|
||||
delegate:comp_delegate
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
Column{
|
||||
id: item_sub_layout
|
||||
Repeater{
|
||||
id:repeater_items
|
||||
model: item_layout.items
|
||||
delegate: delegate_items
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ListView{
|
||||
id:list_root
|
||||
ListView {
|
||||
id: list_root
|
||||
anchors.fill: parent
|
||||
delegate:comp_delegate
|
||||
delegate: delegate_root
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
contentWidth: contentItem.childrenRect.width
|
||||
model: tree_model
|
||||
flickableDirection: Flickable.HorizontalAndVerticalFlick
|
||||
clip: true
|
||||
ScrollBar.vertical: ScrollBar { }
|
||||
ScrollBar.horizontal: ScrollBar { }
|
||||
}
|
||||
|
||||
|
||||
function updateData(items){
|
||||
rootModel.clear()
|
||||
rootModel.append(items)
|
||||
}
|
||||
|
||||
function signleData(){
|
||||
return currentElement
|
||||
}
|
||||
|
||||
function multipData(){
|
||||
return multipElement
|
||||
}
|
||||
|
||||
function createItem(text="Title",expanded=true,items=[]){
|
||||
return {text:text,expanded:expanded,items:items};
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue