mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-09 05:52:41 +00:00
d4d72038bd
It allows transforming model, including submodels outside of the view component consuming the model. Thanks to that now there is no need to create proxies for submodels in view's delegate. It can be done earlies, on the level of the main view. Closes: #12630
272 lines
7.0 KiB
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
|