Browse Source

qml: initial implementation of new wallet conversation

patch-4
Sander van Grieken 4 years ago
parent
commit
e3c63ae395
  1. 190
      electrum/gui/qml/components/NewWalletWizard.qml
  2. 10
      electrum/gui/qml/components/WizardComponent.qml
  3. 205
      electrum/gui/qml/components/WizardComponents.qml
  4. 27
      electrum/gui/qml/components/landing.qml

190
electrum/gui/qml/components/NewWalletWizard.qml

@ -0,0 +1,190 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.1
Dialog {
id: walletwizard
title: qsTr('New Wallet')
modal: true
enter: null // disable transition
property var wizard_data
function _setWizardData(wdata) {
wizard_data = {}
Object.assign(wizard_data, wdata) // deep copy
console.log('wizard data is now :' + JSON.stringify(wizard_data))
}
// helper function to dynamically load wizard page components
// and add them to the SwipeView
// Here we do some manual binding of page.valid -> pages.pagevalid
// to propagate the state without the binding going stale
function _loadNextComponent(comp, wdata={}) {
var page = comp.createObject(pages, {
'visible': Qt.binding(function() {
return pages.currentItem === this
})
})
page.validChanged.connect(function() {
pages.pagevalid = page.valid
} )
page.lastChanged.connect(function() {
pages.lastpage = page.last
} )
Object.assign(page.wizard_data, wdata) // deep copy
pages.pagevalid = page.valid
return page
}
// State transition functions. These functions are called when the 'Next'
// button is pressed. They take data from the component, add it to the
// wizard_data object, and depending on the data create the next page
// in the conversation.
function walletnameDone(d) {
console.log('wallet name done')
wizard_data['wallet_name'] = pages.currentItem.wallet_name
var page = _loadNextComponent(components.wallettype, wizard_data)
page.next.connect(function() {wallettypeDone()})
}
function wallettypeDone(d) {
console.log('wallet type done')
wizard_data['wallet_type'] = pages.currentItem.wallet_type
var page = _loadNextComponent(components.keystore, wizard_data)
page.next.connect(function() {keystoretypeDone()})
}
function keystoretypeDone(d) {
console.log('keystore type done')
wizard_data['keystore_type'] = pages.currentItem.keystore_type
var page
switch(wizard_data['keystore_type']) {
case 'createseed':
page = _loadNextComponent(components.createseed, wizard_data)
page.next.connect(function() {createseedDone()})
break
case 'haveseed':
page = _loadNextComponent(components.haveseed, wizard_data)
page.next.connect(function() {haveseedDone()})
break
// case 'masterkey'
// case 'hardware'
}
}
function createseedDone(d) {
console.log('create seed done')
wizard_data['seed'] = pages.currentItem.seed
var page = _loadNextComponent(components.confirmseed, wizard_data)
page.next.connect(function() {confirmseedDone()})
}
function confirmseedDone(d) {
console.log('confirm seed done')
var page = _loadNextComponent(components.walletpassword, wizard_data)
page.next.connect(function() {walletpasswordDone()})
page.last = true
}
function haveseedDone(d) {
console.log('have seed done')
wizard_data['seed'] = pages.currentItem.seed
var page = _loadNextComponent(components.walletpassword, wizard_data)
page.next.connect(function() {walletpasswordDone()})
page.last = true
}
function walletpasswordDone(d) {
console.log('walletpassword done')
wizard_data['password'] = pages.currentItem.password
wizard_data['encrypt'] = pages.currentItem.encrypt
var page = _loadNextComponent(components.walletpassword, wizard_data)
}
ColumnLayout {
anchors.fill: parent
SwipeView {
id: pages
Layout.fillHeight: true
interactive: false
function prev() {
currentIndex = currentIndex - 1
_setWizardData(pages.contentChildren[currentIndex].wizard_data)
pages.pagevalid = pages.contentChildren[currentIndex].valid
pages.contentChildren[currentIndex+1].destroy()
}
function next() {
currentItem.next()
currentIndex = currentIndex + 1
}
function finalize() {
walletwizard.accept()
}
property bool pagevalid: false
property bool lastpage: false
Component.onCompleted: {
_setWizardData({})
var start = _loadNextComponent(components.walletname)
start.next.connect(function() {walletnameDone()})
}
}
PageIndicator {
id: indicator
Layout.alignment: Qt.AlignHCenter
count: pages.count
currentIndex: pages.currentIndex
}
RowLayout {
Layout.alignment: Qt.AlignHCenter
Button {
visible: pages.currentIndex == 0
text: qsTr("Cancel")
onClicked: walletwizard.close()
}
Button {
visible: pages.currentIndex > 0
text: qsTr('Back')
onClicked: pages.prev()
}
Button {
text: "Next"
visible: !pages.lastpage
enabled: pages.pagevalid
onClicked: pages.next()
}
Button {
text: "Create"
visible: pages.lastpage
enabled: pages.pagevalid
onClicked: pages.finalize()
}
}
}
WizardComponents {
id: components
}
}

10
electrum/gui/qml/components/WizardComponent.qml

@ -0,0 +1,10 @@
import QtQuick 2.0
Item {
signal next
property var wizard_data : ({})
property bool valid
property bool last: false
// onValidChanged: console.log('valid change in component itself')
// onWizard_dataChanged: console.log('wizard data changed in ')
}

205
electrum/gui/qml/components/WizardComponents.qml

@ -0,0 +1,205 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.1
Item {
property Component walletname: Component {
WizardComponent {
valid: wallet_name.text.length > 0
property alias wallet_name: wallet_name.text
GridLayout {
columns: 1
Label { text: qsTr('Wallet name') }
TextField {
id: wallet_name
}
}
}
}
property Component wallettype: Component {
WizardComponent {
valid: wallettypegroup.checkedButton !== null
property string wallet_type
ButtonGroup {
id: wallettypegroup
onCheckedButtonChanged: {
wallet_type = checkedButton.wallettype
}
}
GridLayout {
columns: 1
Label { text: qsTr('What kind of wallet do you want to create?') }
RadioButton {
ButtonGroup.group: wallettypegroup
property string wallettype: 'standard'
checked: true
text: qsTr('Standard Wallet')
}
RadioButton {
enabled: false
ButtonGroup.group: wallettypegroup
property string wallettype: '2fa'
text: qsTr('Wallet with two-factor authentication')
}
RadioButton {
enabled: false
ButtonGroup.group: wallettypegroup
property string wallettype: 'multisig'
text: qsTr('Multi-signature wallet')
}
RadioButton {
enabled: false
ButtonGroup.group: wallettypegroup
property string wallettype: 'import'
text: qsTr('Import Bitcoin addresses or private keys')
}
}
}
}
property Component keystore: Component {
WizardComponent {
valid: keystoregroup.checkedButton !== null
property string keystore_type
ButtonGroup {
id: keystoregroup
onCheckedButtonChanged: {
keystore_type = checkedButton.keystoretype
}
}
GridLayout {
columns: 1
Label { text: qsTr('What kind of wallet do you want to create?') }
RadioButton {
ButtonGroup.group: keystoregroup
property string keystoretype: 'createseed'
checked: true
text: qsTr('Create a new seed')
}
RadioButton {
ButtonGroup.group: keystoregroup
property string keystoretype: 'haveseed'
text: qsTr('I already have a seed')
}
RadioButton {
enabled: false
ButtonGroup.group: keystoregroup
property string keystoretype: 'masterkey'
text: qsTr('Use a master key')
}
RadioButton {
enabled: false
ButtonGroup.group: keystoregroup
property string keystoretype: 'hardware'
text: qsTr('Use a hardware device')
}
}
}
}
property Component createseed: Component {
WizardComponent {
valid: true
property alias seed: seedtext.text
property alias extend: extendcb.checked
GridLayout {
columns: 1
Label { text: qsTr('Generating seed') }
TextArea {
id: seedtext
text: 'test this is a fake seed as you might expect'
readOnly: true
Layout.fillWidth: true
wrapMode: TextInput.WordWrap
}
CheckBox {
id: extendcb
text: qsTr('Extend seed with custom words')
}
}
}
}
property Component haveseed: Component {
WizardComponent {
valid: true
property alias seed: seedtext.text
property alias extend: extendcb.checked
property alias bip39: bip39cb.checked
GridLayout {
columns: 1
Label { text: qsTr('Enter your seed') }
TextArea {
id: seedtext
wrapMode: TextInput.WordWrap
Layout.fillWidth: true
}
CheckBox {
id: extendcb
enabled: true
text: qsTr('Extend seed with custom words')
}
CheckBox {
id: bip39cb
enabled: true
text: qsTr('BIP39')
}
}
}
}
property Component confirmseed: Component {
WizardComponent {
valid: confirm.text !== ''
Layout.fillWidth: true
GridLayout {
Layout.fillWidth: true
columns: 1
Label { text: qsTr('Confirm your seed (re-enter)') }
TextArea {
id: confirm
wrapMode: TextInput.WordWrap
Layout.fillWidth: true
onTextChanged: {
console.log("TODO: verify seed")
}
}
}
}
}
property Component walletpassword: Component {
WizardComponent {
valid: password1.text === password2.text
property alias password: password1.text
property alias encrypt: doencrypt.checked
GridLayout {
columns: 1
Label { text: qsTr('Password protect wallet?') }
TextField {
id: password1
echoMode: TextInput.Password
}
TextField {
id: password2
echoMode: TextInput.Password
}
CheckBox {
id: doencrypt
enabled: password1.text !== ''
text: qsTr('Encrypt wallet')
}
}
}
}
}

27
electrum/gui/qml/components/landing.qml

@ -1,8 +1,10 @@
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Controls 2.3
import QtQml 2.6
Item {
id: rootItem
property string title: 'Network'
property QtObject menu: Menu {
@ -28,7 +30,30 @@ Item {
onClicked: app.stack.push(Qt.resolvedUrl('History.qml'))
}
Button {
text: 'Create Wallet'
onClicked: {
var dialog = newWalletWizard.createObject(rootItem)
dialog.open()
}
}
}
Component {
id: newWalletWizard
NewWalletWizard {
parent: Overlay.overlay
x: 12
y: 12
width: parent.width - 24
height: parent.height - 24
Overlay.modal: Rectangle {
color: "#aa000000"
}
}
}
}

Loading…
Cancel
Save