import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import utils 1.0
import AppLayouts.Wallet.popups 1.0
import AppLayouts.Wallet.controls 1.0
import AppLayouts.stores 1.0
import Models 1.0
import SortFilterProxyModel 0.2
SplitView {
id: root
Pane {
SplitView.fillWidth: true
SplitView.fillHeight: true
ColumnLayout {
id: controlLayout
anchors.fill: parent
// Leave some space so that the popup will be opened without accounting for Layer
ColumnLayout {
Layout.maximumHeight: 50
}
NetworkFilter {
id: networkFilter
Layout.preferredWidth: 200
Layout.preferredHeight: 100
Layout.alignment: Qt.AlignHCenter
allNetworks: simulatedNimModel
layer1Networks: SortFilterProxyModel {
function rowData(index, propName) {
return get(index)[propName]
}
sourceModel: simulatedNimModel
filters: ValueFilter { roleName: "layer"; value: 1; }
}
layer2Networks: SortFilterProxyModel {
sourceModel: simulatedNimModel
filters: [ValueFilter { roleName: "layer"; value: 2; },
ValueFilter { roleName: "isTest"; value: false; }]
}
testNetworks: SortFilterProxyModel {
sourceModel: simulatedNimModel
filters: [ValueFilter { roleName: "layer"; value: 2; },
ValueFilter { roleName: "isTest"; value: true; }]
}
enabledNetworks: SortFilterProxyModel {
sourceModel: simulatedNimModel
filters: ValueFilter { roleName: "isEnabled"; value: true; }
}
onToggleNetwork: (network) => {
if(multiSelection) {
simulatedNimModel.toggleNetwork(network)
} else {
lastSingleSelectionLabel.text = `[${network.chainName}] (NL) - ID: ${network.chainId}, Icon: ${network.iconUrl}`
}
}
multiSelection: multiSelectionCheckbox.checked
isChainVisible: isChainVisibleCheckbox.checked
}
// Dummy item to make space for popup
Item {
id: popupPlaceholder
Layout.preferredWidth: networkSelectPopup.width
Layout.preferredHeight: networkSelectPopup.height
NetworkSelectPopup {
id: networkSelectPopup
layer1Networks: networkFilter.layer1Networks
layer2Networks: networkFilter.layer2Networks
testNetworks: networkFilter.testNetworks
useEnabledRole: false
visible: true
closePolicy: Popup.NoAutoClose
// Simulates a network toggle
onToggleNetwork: (network, networkModel, index) => simulatedNimModel.toggleNetwork(network)
}
}
ColumnLayout {
Layout.preferredHeight: 30
Layout.maximumHeight: 30
}
RowLayout {
Button {
text: "Single Selection Popup"
onClicked: selectPopupLoader.active = true
}
Label {
id: lastSingleSelectionLabel
text: "-"
}
}
Item {
id: singleSelectionPopupPlaceholder
Layout.preferredWidth: selectPopupLoader.item ? selectPopupLoader.item.width : 0
Layout.preferredHeight: selectPopupLoader.item ? selectPopupLoader.item.height : 0
property var currentModel: networkFilter.layer2Networks
property int currentIndex: 0
Loader {
id: selectPopupLoader
active: false
sourceComponent: NetworkSelectPopup {
layer1Networks: networkFilter.layer1Networks
layer2Networks: networkFilter.layer2Networks
testNetworks: networkFilter.testNetworks
singleSelection {
enabled: true
currentModel: singleSelectionPopupPlaceholder.currentModel
currentIndex: singleSelectionPopupPlaceholder.currentIndex
}
onToggleNetwork: (network, networkModel, index) => {
lastSingleSelectionLabel.text = `[${network.chainName}] - ID: ${network.chainId}, Icon: ${network.iconUrl}`
singleSelectionPopupPlaceholder.currentModel = networkModel
singleSelectionPopupPlaceholder.currentIndex = index
}
onClosed: selectPopupLoader.active = false
}
onLoaded: item.open()
}
}
// Vertical separator
ColumnLayout {}
}
}
Pane {
SplitView.minimumWidth: 300
SplitView.fillWidth: true
SplitView.minimumHeight: 300
ColumnLayout {
anchors.fill: parent
ListView {
id: allNetworksListView
Layout.fillWidth: true
Layout.fillHeight: true
model: simulatedNimModel
delegate: ItemDelegate {
width: allNetworksListView.width
implicitHeight: delegateRowLayout.implicitHeight
highlighted: ListView.isCurrentItem
RowLayout {
id: delegateRowLayout
anchors.fill: parent
Column {
Layout.margins: 5
spacing: 3
Label { text: model.chainName }
Row {
spacing: 5
Label { text: `${model.shortName}` }
Label { text: `ID ${model.chainId}` }
CheckBox {
checkState: model.isEnabled ? Qt.Checked : Qt.Unchecked
tristate: true
nextCheckState: () => {
const nextEnabled = (checkState !== Qt.Checked)
availableNetworks.sourceModel.setProperty(availableNetworks.mapToSource(index), "isEnabled", nextEnabled)
Qt.callLater(() => { simulatedNimModel.cloneModel(availableNetworks) })
return nextEnabled ? Qt.Checked : Qt.Unchecked
}
}
}
}
}
onClicked: allNetworksListView.currentIndex = index
}
}
CheckBox {
id: multiSelectionCheckbox
Layout.margins: 5
text: "Multi Selection"
checked: true
}
CheckBox {
id: testModeCheckbox
Layout.margins: 5
text: "Test Networks Mode"
checked: false
onCheckedChanged: Qt.callLater(simulatedNimModel.cloneModel, availableNetworks)
}
CheckBox {
id: isChainVisibleCheckbox
Layout.margins: 5
text: "Is chain visible"
checked: true
}
}
}
SortFilterProxyModel {
id: availableNetworks
// Simulate Nim's way of providing access to data
function rowData(index, propName) {
return get(index)[propName]
}
sourceModel: NetworksModel.allNetworks
filters: ValueFilter { roleName: "isTest"; value: testModeCheckbox.checked; }
}
// Keep a clone so that the UX can be modified without affecting the original model
CloneModel {
id: simulatedNimModel
sourceModel: availableNetworks
roles: ["chainId", "layer", "chainName", "isTest", "isEnabled", "iconUrl", "shortName", "chainColor"]
rolesOverride: [{ role: "enabledState", transform: (mD) => {
return simulatedNimModel.areAllEnabled(sourceModel)
? NetworkSelectPopup.UxEnabledState.AllEnabled
: mD.isEnabled
? NetworkSelectPopup.UxEnabledState.Enabled
: NetworkSelectPopup.UxEnabledState.Disabled
}
}]
/// Simulate the Nim model
function toggleNetwork(network) {
const chainId = network.chainId
let chainIdOnlyEnabled = true
let chainIdOnlyDisabled = true
let allEnabled = true
for (let i = 0; i < simulatedNimModel.count; i++) {
const item = simulatedNimModel.get(i)
if(item.enabledState === NetworkSelectPopup.UxEnabledState.Enabled) {
if(item.chainId !== chainId) {
chainIdOnlyEnabled = false
}
} else if(item.enabledState === NetworkSelectPopup.UxEnabledState.Disabled) {
if(item.chainId !== chainId) {
chainIdOnlyDisabled = false
}
allEnabled = false
} else {
if(item.chainId === chainId) {
chainIdOnlyDisabled = false
chainIdOnlyEnabled = false
}
}
}
for (let i = 0; i < simulatedNimModel.count; i++) {
const item = simulatedNimModel.get(i)
if(allEnabled) {
simulatedNimModel.setProperty(i, "enabledState", item.chainId === chainId ? NetworkSelectPopup.UxEnabledState.Enabled : NetworkSelectPopup.UxEnabledState.Disabled)
} else if(chainIdOnlyEnabled || chainIdOnlyDisabled) {
simulatedNimModel.setProperty(i, "enabledState", NetworkSelectPopup.UxEnabledState.AllEnabled)
} else if(item.chainId === chainId) {
simulatedNimModel.setProperty(i, "enabledState", item.enabledState === NetworkSelectPopup.UxEnabledState.Enabled
? NetworkSelectPopup.UxEnabledState.Disabled
:NetworkSelectPopup.UxEnabledState.Enabled)
}
const haveEnabled = item.enabledState !== NetworkSelectPopup.UxEnabledState.Disabled
if(item.isEnabled !== haveEnabled) {
simulatedNimModel.setProperty(i, "isEnabled", haveEnabled)
}
}
}
function areAllEnabled(modelToCheck) {
for (let i = 0; i < modelToCheck.count; i++) {
if(!(modelToCheck.get(i).isEnabled)) {
return false
}
}
return true
}
}
}