Last active
February 12, 2022 06:30
-
-
Save Iktwo/9cc40a41acfbbe890762edd091cc5900 to your computer and use it in GitHub Desktop.
ExpandableListView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import QtQuick 2.0 | |
// Use Item as root element to control what properties are exposed, without this the delegate could be overwritten and the list would not work as expected | |
Item { | |
id: root | |
// Expose ListView properties | |
property alias model: listView.model | |
property alias clip: listView.clip | |
// Property to control wether or not the list can expand | |
property bool expandable: true | |
// Property to control if the list should read the initial model and expand the elements | |
property bool autoExpanded: true | |
// Property to control if interactive property should be set to false automatically | |
property bool autoDisableInteractiveProperty: true | |
// Property that defines the component to render when the element is compressed | |
property Component compressedItem | |
// Property that defines the component to render when the element is expanded | |
property Component expandedItem | |
ListView { | |
id: listView | |
anchors.fill: parent | |
delegate: Component { | |
Loader { | |
property var view: ListView.view | |
property int itemIndex: index | |
property var dataSource: { | |
try { | |
if (modelData !== undefined) { | |
return modelData | |
} else { | |
return model | |
} | |
} catch(e) { | |
return model | |
} | |
} | |
property var expand: function expanded(value) { | |
// Check if the list expandable, otherwise do nothing (■_■¬) | |
if (root.expandable) { | |
var expanded = itemInternal.expanded | |
// If a value is provided use that, otherwise toggle the current state | |
if (value) { | |
expanded[index] = value | |
} else { | |
expanded[index] = !expanded[index] | |
} | |
itemInternal.expanded = expanded | |
} | |
} | |
sourceComponent: { | |
var item = itemInternal.expanded[index] ? expandedItem : compressedItem | |
try { | |
if (modelData !== undefined && modelData.children !== undefined) { | |
return item | |
} else if (model.children !== undefined){ | |
return item | |
} else { | |
return compressedItem | |
} | |
} catch(e) { | |
if (model !== undefined && model.children !== undefined) { | |
return item | |
} else { | |
return compressedItem | |
} | |
} | |
} | |
onLoaded: { | |
if (autoDisableInteractiveProperty && sourceComponent === expandedItem) { | |
// If the loaded Component is a Flickable the interactive property needs to be disabled for the list to scroll properly | |
try { | |
item.interactive = false | |
} catch(e) { | |
} | |
} | |
} | |
} | |
} | |
// 'Private' internal item that holds expanded information | |
Item { | |
id: itemInternal | |
property var expanded: [] | |
} | |
onCountChanged: { | |
// Check if the list is supposed to auto expand, otherwise do nothing (■_■¬) | |
if (autoExpanded) { | |
var expanded = [] | |
for (var i = 0; i < count; ++i) { | |
if (model[i] !== undefined && model[i].expanded !== undefined) { | |
expanded.push(model[i].expanded) | |
} else if (model.get(i).expanded !== undefined){ | |
expanded.push(model.get(i).expanded) | |
} else { | |
expanded.push(false) | |
} | |
} | |
itemInternal.expanded = expanded | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import QtQuick 2.11 | |
import QtQuick.Window 2.11 | |
Window { | |
visible: true | |
width: 640 | |
height: 480 | |
title: qsTr("Hello World") | |
property var sourceData: [ | |
{ | |
"title": "item1", | |
"expanded": false, | |
"children": [{ | |
"title": "subtitle1" | |
}, | |
{ | |
"title": "subtitle2" | |
}, | |
{ | |
"title": "subtitle3" | |
} | |
] | |
}, { | |
"title": "title2", | |
"expanded": false | |
}, | |
{ | |
"title": "title3", | |
"expanded": false | |
}, | |
{ | |
"title": "title4", | |
"expanded": true, | |
"children": [{ | |
"title": "subtitle1" | |
}, | |
{ | |
"title": "subtitle2" | |
}, | |
{ | |
"title": "subtitle3" | |
}, | |
{ | |
"title": "subtitle3" | |
} | |
] | |
}, | |
{ | |
"title": "title5", | |
"expanded": false | |
} | |
] | |
ListModel { | |
id: fruitModel | |
ListElement { | |
title: "Apple" | |
cost: 2.45 | |
} | |
ListElement { | |
title: "Orange" | |
cost: 3.25 | |
} | |
ListElement { | |
title: "Banana" | |
cost: 1.95 | |
expanded: true | |
children: [ListElement { | |
title: "Inner Banana" | |
cost: 1.95 | |
expanded: true | |
}, | |
ListElement { | |
title: "Inner Banana 2" | |
cost: 1.95 | |
expanded: true | |
}] | |
} | |
} | |
ExpandableListView { | |
anchors { | |
left: parent.left | |
top: parent.top | |
bottom: parent.bottom | |
} | |
width: parent.width / 2 | |
model: sourceData | |
compressedItem: Rectangle { | |
width: view.width | |
height: view.height / 5 | |
color: "#3498db" | |
border { | |
color: "black" | |
width: 1 | |
} | |
Text { | |
anchors.centerIn: parent | |
text: itemIndex + " - " + dataSource.title | |
} | |
MouseArea { | |
anchors.fill: parent | |
onClicked: { | |
expand() | |
} | |
} | |
} | |
expandedItem: ListView { | |
height: count * 100 | |
width: view.width | |
model: dataSource.children | |
delegate: Rectangle { | |
color: "#56bafd" | |
border { | |
color: "black" | |
width: 1 | |
} | |
height: 100 | |
width: ListView.view.width | |
Text { | |
anchors.centerIn: parent | |
text: itemIndex + " - " + modelData.title | |
color: "red" | |
} | |
} | |
MouseArea { | |
anchors.fill: parent | |
onClicked: { | |
expand() | |
} | |
} | |
} | |
} | |
ExpandableListView { | |
anchors { | |
right: parent.right | |
top: parent.top | |
bottom: parent.bottom | |
} | |
model: fruitModel | |
width: parent.width / 2 | |
autoExpanded: true | |
compressedItem: Rectangle { | |
width: view.width | |
height: view.height / 5 | |
color: "#3498db" | |
border { | |
color: "black" | |
width: 1 | |
} | |
Text { | |
anchors.centerIn: parent | |
text: itemIndex + " - " + dataSource.title | |
} | |
MouseArea { | |
anchors.fill: parent | |
onClicked: { | |
expand() | |
} | |
} | |
} | |
expandedItem: ListView { | |
height: count * 100 | |
width: view.width | |
model: dataSource.children | |
delegate: Rectangle { | |
color: "#56bafd" | |
border { | |
color: "black" | |
width: 1 | |
} | |
height: 100 | |
width: ListView.view.width | |
Text { | |
anchors.centerIn: parent | |
text: itemIndex + " - " + model.title | |
color: "red" | |
} | |
} | |
MouseArea { | |
anchors.fill: parent | |
onClicked: { | |
expand() | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment