qml: initial implementation of new wallet conversation
This commit is contained in:
190
electrum/gui/qml/components/NewWalletWizard.qml
Normal file
190
electrum/gui/qml/components/NewWalletWizard.qml
Normal file
@@ -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
Normal file
10
electrum/gui/qml/components/WizardComponent.qml
Normal file
@@ -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
Normal file
205
electrum/gui/qml/components/WizardComponents.qml
Normal file
@@ -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')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user