4 changed files with 431 additions and 1 deletions
@ -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 |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
@ -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 ') |
||||||
|
} |
||||||
@ -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') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue