diff --git a/src/app/modules/main/networks/model.nim b/src/app/modules/main/networks/model.nim index 07efc5d70f..de4a543d6e 100644 --- a/src/app/modules/main/networks/model.nim +++ b/src/app/modules/main/networks/model.nim @@ -3,7 +3,7 @@ import NimQml, Tables, strutils, strformat import ./item type - ModelRole {.pure.} = enum + ModelRole* {.pure.} = enum ChainId = UserRole + 1, NativeCurrencyDecimals Layer @@ -48,7 +48,7 @@ QtObject: read = getCount notify = countChanged - method rowCount(self: Model, index: QModelIndex = nil): int = + method rowCount*(self: Model, index: QModelIndex = nil): int = return self.items.len method roleNames(self: Model): Table[int, string] = @@ -109,7 +109,7 @@ QtObject: of ModelRole.Balance: 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): return let item = self.items[index] diff --git a/src/app/modules/main/networks/networks_extra_store_proxy.nim b/src/app/modules/main/networks/networks_extra_store_proxy.nim new file mode 100644 index 0000000000..e250cbcd63 --- /dev/null +++ b/src/app/modules/main/networks/networks_extra_store_proxy.nim @@ -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) \ No newline at end of file diff --git a/src/app/modules/main/networks/view.nim b/src/app/modules/main/networks/view.nim index 6915a45837..bdaed1e477 100644 --- a/src/app/modules/main/networks/view.nim +++ b/src/app/modules/main/networks/view.nim @@ -3,6 +3,7 @@ import Tables, NimQml, sequtils, sugar import ../../../../app_service/service/network/dto import ./io_interface import ./model +import ./networks_extra_store_proxy import ./item QtObject: @@ -14,6 +15,9 @@ QtObject: layer1: Model layer2: Model 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) = self.QObject.setup @@ -28,6 +32,8 @@ QtObject: result.layer1 = newModel() result.layer2 = newModel() result.enabled = newModel() + result.layer1Proxy = nil + result.layer2Proxy = nil result.setup() proc areTestNetworksEnabledChanged*(self: View) {.signal.} @@ -98,7 +104,7 @@ QtObject: n.shortName, balance, )) - + self.all.setItems(items) self.layer1.setItems(items.filter(i => i.getLayer() == 1)) self.layer2.setItems(items.filter(i => i.getLayer() == 2)) @@ -114,7 +120,29 @@ QtObject: proc toggleNetwork*(self: View, chainId: int) {.slot.} = self.delegate.toggleNetwork(chainId) - proc toggleTestNetworksEnabled*(self: View) {.slot.} = + proc toggleTestNetworksEnabled*(self: View) {.slot.} = self.delegate.toggleTestNetworksEnabled() self.areTestNetworksEnabled = not self.areTestNetworksEnabled 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 \ No newline at end of file diff --git a/ui/app/AppLayouts/Profile/stores/AdvancedStore.qml b/ui/app/AppLayouts/Profile/stores/AdvancedStore.qml index deb3cfc53f..0a849874e1 100644 --- a/ui/app/AppLayouts/Profile/stores/AdvancedStore.qml +++ b/ui/app/AppLayouts/Profile/stores/AdvancedStore.qml @@ -7,7 +7,6 @@ QtObject { property var advancedModule // Advanced Module Properties - property string currentChainId: advancedModule? advancedModule.currentChainId : 0 property string fleet: advancedModule? advancedModule.fleet : "" property string bloomLevel: advancedModule? advancedModule.bloomLevel : "" property bool wakuV2LightClientEnabled: advancedModule? advancedModule.wakuV2LightClientEnabled : false diff --git a/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml b/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml index 3cd8dd2168..8729c80ef3 100644 --- a/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml +++ b/ui/app/AppLayouts/Wallet/popups/NetworkSelectPopup.qml @@ -12,7 +12,7 @@ import utils 1.0 // TODO: replace with StatusModal Popup { - id: popup + id: root modal: false width: 360 height: 432 @@ -25,6 +25,9 @@ Popup { property var layer2Networks property var testNetworks + // If true NetworksExtraStoreProxy expected for layer1Networks and layer2Networks properties + property bool useNetworksExtraStoreProxy: false + signal toggleNetwork(int chainId) background: Rectangle { @@ -45,8 +48,8 @@ Popup { contentItem: StatusScrollView { id: scrollView contentHeight: content.height - width: popup.width - height: popup.height + width: root.width + height: root.height padding: 0 ScrollBar.horizontal.policy: ScrollBar.AlwaysOff @@ -61,7 +64,7 @@ Popup { width: parent.width height: parent.height objectName: "networkSelectPopupChainRepeaterLayer1" - model: popup.layer1Networks + model: root.layer1Networks delegate: chainItem } @@ -80,14 +83,14 @@ Popup { Repeater { id: chainRepeater2 - model: popup.layer2Networks + model: root.layer2Networks delegate: chainItem } Repeater { id: chainRepeater3 - model: popup.testNetworks + model: root.testNetworks delegate: chainItem } @@ -111,10 +114,12 @@ Popup { components: [ StatusCheckBox { id: checkBox - checked: model.isEnabled + checked: root.useNetworksExtraStoreProxy ? model.isActive : model.isEnabled onCheckedChanged: { - if (model.isEnabled !== checked) { - popup.toggleNetwork(model.chainId) + if(root.useNetworksExtraStoreProxy && model.isActive !== checked) { + model.isActive = checked + } else if (model.isEnabled !== checked) { + root.toggleNetwork(model.chainId) } } } diff --git a/ui/app/AppLayouts/Wallet/popups/ReceiveModal.qml b/ui/app/AppLayouts/Wallet/popups/ReceiveModal.qml index 99da92dfcf..d1a96a4198 100644 --- a/ui/app/AppLayouts/Wallet/popups/ReceiveModal.qml +++ b/ui/app/AppLayouts/Wallet/popups/ReceiveModal.qml @@ -19,14 +19,14 @@ import shared.popups 1.0 import "../stores" StatusModal { - id: popup + id: root property var selectedAccount property string networkPrefix: "" property string completeAddressWithNetworkPrefix onSelectedAccountChanged: { - if (selectedAccount.address) { + if (selectedAccount && selectedAccount.address) { txtWalletAddress.text = selectedAccount.address } } @@ -47,23 +47,23 @@ StatusModal { target: RootStore.enabledNetworks function onModelReset() { if(RootStore.enabledNetworks.count === 0) - popup.networkPrefix = "" + root.networkPrefix = "" } } hasFloatingButtons: true advancedHeaderComponent: AccountsModalHeader { model: RootStore.accounts - selectedAccount: popup.selectedAccount + selectedAccount: root.selectedAccount changeSelectedAccount: function(newAccount, newIndex) { - popup.selectedAccount = newAccount + root.selectedAccount = newAccount } showAllWalletTypes: true } contentItem: Column { id: layout - width: popup.width + width: root.width topPadding: Style.current.xlPadding spacing: Style.current.bigPadding @@ -97,16 +97,21 @@ StatusModal { flow: Grid.TopToBottom columns: need2Columns ? 2 : 1 spacing: 5 + property var networkProxies: [RootStore.layer1NetworksProxy, RootStore.layer2NetworksProxy] Repeater { - model: RootStore.enabledNetworks - delegate: InformationTag { - tagPrimaryLabel.text: model.shortName - tagPrimaryLabel.color: model.chainColor - image.source: Style.svg("tiny/" + model.iconUrl) - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: selectPopup.open() + model: multiChainList.networkProxies.length + delegate: Repeater { + model: multiChainList.networkProxies[index] + delegate: InformationTag { + tagPrimaryLabel.text: model.shortName + tagPrimaryLabel.color: model.chainColor + image.source: Style.svg("tiny/" + model.iconUrl) + visible: model.isActive + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: selectPopup.open() + } } } } @@ -200,15 +205,21 @@ StatusModal { id: networksLabel spacing: -1 Repeater { - model: RootStore.enabledNetworks - delegate: StatusBaseText { - font.pixelSize: 15 - color: chainColor - text: shortName + ":" - Component.onCompleted: { - if(index === 0) - popup.networkPrefix = "" - popup.networkPrefix +=text + model: multiChainList.networkProxies.length + delegate: Repeater { + model: multiChainList.networkProxies[index] + delegate: StatusBaseText { + font.pixelSize: 15 + color: chainColor + text: shortName + ":" + visible: model.isActive + onVisibleChanged: { + if (visible) { + networkPrefix += text + } else { + networkPrefix = networkPrefix.replace(text, "") + } + } } } } @@ -241,14 +252,16 @@ StatusModal { NetworkSelectPopup { id: selectPopup + x: multiChainList.x + Style.current.xlPadding + Style.current.halfPadding 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: [ @@ -272,8 +285,8 @@ StatusModal { textToCopy: txtWalletAddress.text } PropertyChanges { - target: popup - completeAddressWithNetworkPrefix: popup.selectedAccount.address + target: root + completeAddressWithNetworkPrefix: root.selectedAccount.address } }, State { @@ -293,11 +306,11 @@ StatusModal { } PropertyChanges { target: copyToClipBoard - textToCopy: popup.networkPrefix + txtWalletAddress.text + textToCopy: root.networkPrefix + txtWalletAddress.text } PropertyChanges { - target: popup - completeAddressWithNetworkPrefix: popup.networkPrefix + popup.selectedAccount.address + target: root + completeAddressWithNetworkPrefix: root.networkPrefix + root.selectedAccount.address } } ] diff --git a/ui/app/AppLayouts/Wallet/stores/RootStore.qml b/ui/app/AppLayouts/Wallet/stores/RootStore.qml index cb1d2c6b7e..b10b7ac8a7 100644 --- a/ui/app/AppLayouts/Wallet/stores/RootStore.qml +++ b/ui/app/AppLayouts/Wallet/stores/RootStore.qml @@ -48,6 +48,8 @@ QtObject { property var testNetworks: networksModule.test property var enabledNetworks: networksModule.enabled property var allNetworks: networksModule.all + property var layer1NetworksProxy: networksModule.layer1Proxy + property var layer2NetworksProxy: networksModule.layer2Proxy property var cryptoRampServicesModel: walletSectionBuySellCrypto.model