status-desktop/storybook/pages/SubmodelProxyModelPage.qml

272 lines
7.0 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import Storybook 1.0
import SortFilterProxyModel 0.2
Item {
id: root
readonly property int numberOfTokens: 2000
readonly property var colors: [
"purple", "lightgreen", "red", "blue", "darkgreen"
]
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
ListModel {
id: networksModel
ListElement {
chainId: "1"
name: "Mainnet"
color: "purple"
}
ListElement {
chainId: "2"
name: "Optimism"
color: "lightgreen"
}
ListElement {
chainId: "3"
name: "Status"
color: "red"
}
ListElement {
chainId: "4"
name: "Abitrum"
color: "blue"
}
ListElement {
chainId: "5"
name: "Sepolia"
color: "darkgreen"
}
}
ListModel {
id: tokensModel
Component.onCompleted: {
// Populate model with given number of tokens containing random
// balances
const numberOfTokens = root.numberOfTokens
const tokens = []
const chainIds = []
for (let n = 0; n < networksModel.count; n++)
chainIds.push(networksModel.get(n).chainId)
for (let i = 0; i < numberOfTokens; i++) {
const balances = []
const numberOfBalances = 1 + getRandomInt(networksModel.count)
const chainIdsCpy = [...chainIds]
for (let i = 0; i < numberOfBalances; i++) {
const chainId = chainIdsCpy.splice(
getRandomInt(chainIdsCpy.length), 1)[0]
balances.push({
chainId: chainId,
balance: 1 + getRandomInt(200)
})
}
tokens.push({ name: `Token ${i + 1}`, balances })
}
append(tokens)
}
}
// Proxy model joining networksModel to submodels under "balances" role.
// Additionally submodel is filtered and sorted via SFPM. Submodel is
// accessible via "submodel" context property.
SubmodelProxyModel {
id: submodelProxyModel
sourceModel: tokensModel
delegateModel: SortFilterProxyModel {
readonly property LeftJoinModel joinModel: LeftJoinModel {
leftModel: submodel
rightModel: networksModel
joinRole: "chainId"
}
sourceModel: joinModel
filters: ExpressionFilter {
expression: balance >= thresholdSlider.value
}
sorters: RoleSorter {
roleName: "name"
enabled: sortCheckBox.checked
}
}
submodelRoleName: "balances"
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
// ListView consuming model don't have to do any transformation
// of the submodels internally because it's handled externally via
// SubmodelProxyModel.
ListView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
reuseItems: true
ScrollBar.vertical: ScrollBar {}
clip: true
spacing: 18
model: submodelProxyModel
delegate: ColumnLayout {
id: delegateRoot
width: ListView.view.width
height: 46
spacing: 0
readonly property var balances: model.balances
Label {
Layout.fillWidth: true
text: model.name
font.bold: true
}
RowLayout {
spacing: 14
Layout.fillWidth: true
Repeater {
model: delegateRoot.balances
Rectangle {
width: label.implicitWidth * 1.5
height: label.implicitHeight * 2
color: "transparent"
border.width: 2
border.color: model.color
Label {
id: label
anchors.centerIn: parent
text: `${model.name} (${model.balance})`
font.pixelSize: 10
}
}
}
}
}
}
Rectangle {
Layout.preferredWidth: 1
Layout.fillHeight: true
Layout.rightMargin: 20
color: "lightgray"
}
ListView {
Layout.preferredWidth: 150
Layout.fillHeight: true
spacing: 20
model: networksModel
delegate: ColumnLayout {
width: ListView.view.width
Label {
Layout.fillWidth: true
text: model.name
font.bold: true
}
Rectangle {
Layout.preferredWidth: changeColorButton.width
Layout.preferredHeight: 10
color: model.color
}
Button {
id: changeColorButton
text: "Change color"
onClicked: {
const currentIdx = root.colors.indexOf(model.color)
const numberOfColors = root.colors.length
const nextIdx = (currentIdx + 1) % numberOfColors
networksModel.setProperty(model.index, "color",
root.colors[nextIdx])
}
}
}
}
}
MenuSeparator {
Layout.fillWidth: true
}
RowLayout {
Label {
text: `Number of tokens: ${listView.count}, minimum balance:`
}
Slider {
id: thresholdSlider
from: 0
to: 201
stepSize: 1
}
Label {
text: thresholdSlider.value
}
CheckBox {
id: sortCheckBox
text: "sort networks by name"
}
}
}
}
// category: Models