fix() don't change global network selection in receive modal

Adds a networks proxy model to be used with the original source model
for visualization and independent selection of isEnabled (as isActive) for a custom
purpose.

Use the proxy in the receive modal dialog for selection of networks
to be included in the address. This way the view follows the original
model but allows independent selection of networks.

Closes: #8180
This commit is contained in:
Stefan 2022-11-12 11:18:18 +02:00 committed by Stefan Dunca
parent 7bd9808476
commit 7d9f13e4bd
7 changed files with 185 additions and 49 deletions

View File

@ -3,7 +3,7 @@ import NimQml, Tables, strutils, strformat
import ./item import ./item
type type
ModelRole {.pure.} = enum ModelRole* {.pure.} = enum
ChainId = UserRole + 1, ChainId = UserRole + 1,
NativeCurrencyDecimals NativeCurrencyDecimals
Layer Layer
@ -48,7 +48,7 @@ QtObject:
read = getCount read = getCount
notify = countChanged notify = countChanged
method rowCount(self: Model, index: QModelIndex = nil): int = method rowCount*(self: Model, index: QModelIndex = nil): int =
return self.items.len return self.items.len
method roleNames(self: Model): Table[int, string] = method roleNames(self: Model): Table[int, string] =
@ -109,7 +109,7 @@ QtObject:
of ModelRole.Balance: of ModelRole.Balance:
result = newQVariant(item.getBalance()) result = newQVariant(item.getBalance())
proc rowData(self: Model, index: int, column: string): string {.slot.} = proc rowData*(self: Model, index: int, column: string): string {.slot.} =
if (index >= self.items.len): if (index >= self.items.len):
return return
let item = self.items[index] let item = self.items[index]

View File

@ -0,0 +1,89 @@
import NimQml, Tables, strutils
import ./model
# Proxy data model for the Networks data model with additional role; see isActiveRoleName
# isEnabled values are copied from the original model into isActiveRoleName values
const isActiveRoleName = "isActive"
QtObject:
type
NetworksExtraStoreProxy* = ref object of QAbstractListModel
sourceModel: Model
activeNetworks: seq[bool]
extraRole: tuple[roleId: int, roleName: string]
proc delete(self: NetworksExtraStoreProxy) =
self.sourceModel = nil
self.activeNetworks = @[]
self.QAbstractListModel.delete
proc setup(self: NetworksExtraStoreProxy) =
self.QAbstractListModel.setup
proc updateActiveNetworks(self: NetworksExtraStoreProxy, sourceModel: Model) =
var tmpSeq = newSeq[bool](sourceModel.rowCount())
for i in 0 ..< sourceModel.rowCount():
tmpSeq[i] = sourceModel.data(sourceModel.index(i, 0, newQModelIndex()), ModelRole.IsEnabled.int).boolVal()
self.activeNetworks = tmpSeq
proc newNetworksExtraStoreProxy*(sourceModel: Model): NetworksExtraStoreProxy =
new(result, delete)
result.sourceModel = sourceModel
# assign past last role element
result.extraRole = (0, isActiveRoleName)
for k in sourceModel.roleNames().keys:
if k > result.extraRole.roleId:
result.extraRole.roleId = k
result.extraRole.roleId += 1
result.updateactiveNetworks(sourceModel)
result.setup
signalConnect(result.sourceModel, "countChanged()", result, "onCountChanged()")
proc countChanged(self: NetworksExtraStoreProxy) {.signal.}
# Nimqml doesn't support connecting signals to other signals
proc onCountChanged(self: NetworksExtraStoreProxy) {.slot.} =
self.updateActiveNetworks(self.sourceModel)
self.countChanged()
proc getCount(self: NetworksExtraStoreProxy): int {.slot.} =
return self.sourceModel.rowCount()
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount(self: NetworksExtraStoreProxy, index: QModelIndex = nil): int =
return self.sourceModel.rowCount()
method roleNames(self: NetworksExtraStoreProxy): Table[int, string] =
var srcRoles = self.sourceModel.roleNames()
srcRoles.add(self.extraRole.roleId, self.extraRole.roleName)
return srcRoles
method data(self: NetworksExtraStoreProxy, index: QModelIndex, role: int): QVariant =
if role == self.extraRole.roleId:
if index.row() < 0 or index.row() >= self.activeNetworks.len:
return QVariant()
return newQVariant(self.activeNetworks[index.row()])
return self.sourceModel.data(index, role)
method setData*(self: NetworksExtraStoreProxy, index: QModelIndex, value: QVariant, role: int): bool =
if role == self.extraRole.roleId:
if index.row() < 0 or index.row() >= self.activeNetworks.len:
return false
self.activeNetworks[index.row()] = value.boolVal()
self.dataChanged(index, index, [self.extraRole.roleId])
return true
return self.sourceModel.setData(index, value, role)
proc rowData(self: NetworksExtraStoreProxy, index: int, column: string): string {.slot.} =
if column == isActiveRoleName:
if index < 0 or index >= self.activeNetworks.len:
return ""
return $self.activeNetworks[index]
return self.sourceModel.rowData(index, column)

View File

@ -3,6 +3,7 @@ import Tables, NimQml, sequtils, sugar
import ../../../../app_service/service/network/dto import ../../../../app_service/service/network/dto
import ./io_interface import ./io_interface
import ./model import ./model
import ./networks_extra_store_proxy
import ./item import ./item
QtObject: QtObject:
@ -14,6 +15,9 @@ QtObject:
layer1: Model layer1: Model
layer2: Model layer2: Model
areTestNetworksEnabled: bool areTestNetworksEnabled: bool
# Lazy initized but here to keep a reference to the object not to be GCed
layer1Proxy: NetworksExtraStoreProxy
layer2Proxy: NetworksExtraStoreProxy
proc setup(self: View) = proc setup(self: View) =
self.QObject.setup self.QObject.setup
@ -28,6 +32,8 @@ QtObject:
result.layer1 = newModel() result.layer1 = newModel()
result.layer2 = newModel() result.layer2 = newModel()
result.enabled = newModel() result.enabled = newModel()
result.layer1Proxy = nil
result.layer2Proxy = nil
result.setup() result.setup()
proc areTestNetworksEnabledChanged*(self: View) {.signal.} proc areTestNetworksEnabledChanged*(self: View) {.signal.}
@ -118,3 +124,25 @@ QtObject:
self.delegate.toggleTestNetworksEnabled() self.delegate.toggleTestNetworksEnabled()
self.areTestNetworksEnabled = not self.areTestNetworksEnabled self.areTestNetworksEnabled = not self.areTestNetworksEnabled
self.areTestNetworksEnabledChanged() self.areTestNetworksEnabledChanged()
proc layer1ProxyChanged*(self: View) {.signal.}
proc getLayer1Proxy(self: View): QVariant {.slot.} =
if self.layer1Proxy.isNil:
self.layer1Proxy = newNetworksExtraStoreProxy(self.layer1)
return newQVariant(self.layer1Proxy)
QtProperty[QVariant] layer1Proxy:
read = getLayer1Proxy
notify = layer1ProxyChanged
proc layer2ProxyChanged*(self: View) {.signal.}
proc getLayer2Proxy(self: View): QVariant {.slot.} =
if self.layer2Proxy.isNil:
self.layer2Proxy = newNetworksExtraStoreProxy(self.layer2)
return newQVariant(self.layer2Proxy)
QtProperty[QVariant] layer2Proxy:
read = getLayer2Proxy
notify = layer2ProxyChanged

View File

@ -7,7 +7,6 @@ QtObject {
property var advancedModule property var advancedModule
// Advanced Module Properties // Advanced Module Properties
property string currentChainId: advancedModule? advancedModule.currentChainId : 0
property string fleet: advancedModule? advancedModule.fleet : "" property string fleet: advancedModule? advancedModule.fleet : ""
property string bloomLevel: advancedModule? advancedModule.bloomLevel : "" property string bloomLevel: advancedModule? advancedModule.bloomLevel : ""
property bool wakuV2LightClientEnabled: advancedModule? advancedModule.wakuV2LightClientEnabled : false property bool wakuV2LightClientEnabled: advancedModule? advancedModule.wakuV2LightClientEnabled : false

View File

@ -12,7 +12,7 @@ import utils 1.0
// TODO: replace with StatusModal // TODO: replace with StatusModal
Popup { Popup {
id: popup id: root
modal: false modal: false
width: 360 width: 360
height: 432 height: 432
@ -25,6 +25,9 @@ Popup {
property var layer2Networks property var layer2Networks
property var testNetworks property var testNetworks
// If true NetworksExtraStoreProxy expected for layer1Networks and layer2Networks properties
property bool useNetworksExtraStoreProxy: false
signal toggleNetwork(int chainId) signal toggleNetwork(int chainId)
background: Rectangle { background: Rectangle {
@ -45,8 +48,8 @@ Popup {
contentItem: StatusScrollView { contentItem: StatusScrollView {
id: scrollView id: scrollView
contentHeight: content.height contentHeight: content.height
width: popup.width width: root.width
height: popup.height height: root.height
padding: 0 padding: 0
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
@ -61,7 +64,7 @@ Popup {
width: parent.width width: parent.width
height: parent.height height: parent.height
objectName: "networkSelectPopupChainRepeaterLayer1" objectName: "networkSelectPopupChainRepeaterLayer1"
model: popup.layer1Networks model: root.layer1Networks
delegate: chainItem delegate: chainItem
} }
@ -80,14 +83,14 @@ Popup {
Repeater { Repeater {
id: chainRepeater2 id: chainRepeater2
model: popup.layer2Networks model: root.layer2Networks
delegate: chainItem delegate: chainItem
} }
Repeater { Repeater {
id: chainRepeater3 id: chainRepeater3
model: popup.testNetworks model: root.testNetworks
delegate: chainItem delegate: chainItem
} }
@ -111,10 +114,12 @@ Popup {
components: [ components: [
StatusCheckBox { StatusCheckBox {
id: checkBox id: checkBox
checked: model.isEnabled checked: root.useNetworksExtraStoreProxy ? model.isActive : model.isEnabled
onCheckedChanged: { onCheckedChanged: {
if (model.isEnabled !== checked) { if(root.useNetworksExtraStoreProxy && model.isActive !== checked) {
popup.toggleNetwork(model.chainId) model.isActive = checked
} else if (model.isEnabled !== checked) {
root.toggleNetwork(model.chainId)
} }
} }
} }

View File

@ -19,14 +19,14 @@ import shared.popups 1.0
import "../stores" import "../stores"
StatusModal { StatusModal {
id: popup id: root
property var selectedAccount property var selectedAccount
property string networkPrefix: "" property string networkPrefix: ""
property string completeAddressWithNetworkPrefix property string completeAddressWithNetworkPrefix
onSelectedAccountChanged: { onSelectedAccountChanged: {
if (selectedAccount.address) { if (selectedAccount && selectedAccount.address) {
txtWalletAddress.text = selectedAccount.address txtWalletAddress.text = selectedAccount.address
} }
} }
@ -47,23 +47,23 @@ StatusModal {
target: RootStore.enabledNetworks target: RootStore.enabledNetworks
function onModelReset() { function onModelReset() {
if(RootStore.enabledNetworks.count === 0) if(RootStore.enabledNetworks.count === 0)
popup.networkPrefix = "" root.networkPrefix = ""
} }
} }
hasFloatingButtons: true hasFloatingButtons: true
advancedHeaderComponent: AccountsModalHeader { advancedHeaderComponent: AccountsModalHeader {
model: RootStore.accounts model: RootStore.accounts
selectedAccount: popup.selectedAccount selectedAccount: root.selectedAccount
changeSelectedAccount: function(newAccount, newIndex) { changeSelectedAccount: function(newAccount, newIndex) {
popup.selectedAccount = newAccount root.selectedAccount = newAccount
} }
showAllWalletTypes: true showAllWalletTypes: true
} }
contentItem: Column { contentItem: Column {
id: layout id: layout
width: popup.width width: root.width
topPadding: Style.current.xlPadding topPadding: Style.current.xlPadding
spacing: Style.current.bigPadding spacing: Style.current.bigPadding
@ -97,12 +97,16 @@ StatusModal {
flow: Grid.TopToBottom flow: Grid.TopToBottom
columns: need2Columns ? 2 : 1 columns: need2Columns ? 2 : 1
spacing: 5 spacing: 5
property var networkProxies: [RootStore.layer1NetworksProxy, RootStore.layer2NetworksProxy]
Repeater { Repeater {
model: RootStore.enabledNetworks model: multiChainList.networkProxies.length
delegate: Repeater {
model: multiChainList.networkProxies[index]
delegate: InformationTag { delegate: InformationTag {
tagPrimaryLabel.text: model.shortName tagPrimaryLabel.text: model.shortName
tagPrimaryLabel.color: model.chainColor tagPrimaryLabel.color: model.chainColor
image.source: Style.svg("tiny/" + model.iconUrl) image.source: Style.svg("tiny/" + model.iconUrl)
visible: model.isActive
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
@ -110,6 +114,7 @@ StatusModal {
} }
} }
} }
}
StatusRoundButton { StatusRoundButton {
width: 32 width: 32
height: 32 height: 32
@ -200,15 +205,21 @@ StatusModal {
id: networksLabel id: networksLabel
spacing: -1 spacing: -1
Repeater { Repeater {
model: RootStore.enabledNetworks model: multiChainList.networkProxies.length
delegate: Repeater {
model: multiChainList.networkProxies[index]
delegate: StatusBaseText { delegate: StatusBaseText {
font.pixelSize: 15 font.pixelSize: 15
color: chainColor color: chainColor
text: shortName + ":" text: shortName + ":"
Component.onCompleted: { visible: model.isActive
if(index === 0) onVisibleChanged: {
popup.networkPrefix = "" if (visible) {
popup.networkPrefix +=text networkPrefix += text
} else {
networkPrefix = networkPrefix.replace(text, "")
}
}
} }
} }
} }
@ -241,14 +252,16 @@ StatusModal {
NetworkSelectPopup { NetworkSelectPopup {
id: selectPopup id: selectPopup
x: multiChainList.x + Style.current.xlPadding + Style.current.halfPadding x: multiChainList.x + Style.current.xlPadding + Style.current.halfPadding
y: centralLayout.y y: centralLayout.y
layer1Networks: RootStore.layer1Networks
layer2Networks: RootStore.layer2Networks
testNetworks: RootStore.testNetworks
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
onToggleNetwork: (chainId) => RootStore.toggleNetwork(chainId) layer1Networks: RootStore.layer1NetworksProxy
layer2Networks: RootStore.layer2NetworksProxy
testNetworks: RootStore.testNetworks
useNetworksExtraStoreProxy: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
} }
states: [ states: [
@ -272,8 +285,8 @@ StatusModal {
textToCopy: txtWalletAddress.text textToCopy: txtWalletAddress.text
} }
PropertyChanges { PropertyChanges {
target: popup target: root
completeAddressWithNetworkPrefix: popup.selectedAccount.address completeAddressWithNetworkPrefix: root.selectedAccount.address
} }
}, },
State { State {
@ -293,11 +306,11 @@ StatusModal {
} }
PropertyChanges { PropertyChanges {
target: copyToClipBoard target: copyToClipBoard
textToCopy: popup.networkPrefix + txtWalletAddress.text textToCopy: root.networkPrefix + txtWalletAddress.text
} }
PropertyChanges { PropertyChanges {
target: popup target: root
completeAddressWithNetworkPrefix: popup.networkPrefix + popup.selectedAccount.address completeAddressWithNetworkPrefix: root.networkPrefix + root.selectedAccount.address
} }
} }
] ]

View File

@ -48,6 +48,8 @@ QtObject {
property var testNetworks: networksModule.test property var testNetworks: networksModule.test
property var enabledNetworks: networksModule.enabled property var enabledNetworks: networksModule.enabled
property var allNetworks: networksModule.all property var allNetworks: networksModule.all
property var layer1NetworksProxy: networksModule.layer1Proxy
property var layer2NetworksProxy: networksModule.layer2Proxy
property var cryptoRampServicesModel: walletSectionBuySellCrypto.model property var cryptoRampServicesModel: walletSectionBuySellCrypto.model