mirror of
https://github.com/monero-project/monero-gui.git
synced 2024-11-17 00:07:51 +00:00
Add support for creating hardware wallet
This commit is contained in:
parent
c3f41ae003
commit
9bb6a25f31
11 changed files with 282 additions and 8 deletions
BIN
images/createWalletFromDevice.png
Executable file
BIN
images/createWalletFromDevice.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
8
main.qml
8
main.qml
|
@ -222,6 +222,9 @@ ApplicationWindow {
|
||||||
if (typeof wizard.m_wallet !== 'undefined') {
|
if (typeof wizard.m_wallet !== 'undefined') {
|
||||||
console.log("using wizard wallet")
|
console.log("using wizard wallet")
|
||||||
//Set restoreHeight
|
//Set restoreHeight
|
||||||
|
if (persistentSettings.restore_height == 0 && persistentSettings.is_recovering_from_device && walletManager.localDaemonSynced()) {
|
||||||
|
persistentSettings.restore_height = walletManager.blockchainHeight() - 1;
|
||||||
|
}
|
||||||
if(persistentSettings.restore_height > 0){
|
if(persistentSettings.restore_height > 0){
|
||||||
// We store restore height in own variable for performance reasons.
|
// We store restore height in own variable for performance reasons.
|
||||||
restoreHeight = persistentSettings.restore_height
|
restoreHeight = persistentSettings.restore_height
|
||||||
|
@ -331,7 +334,9 @@ ApplicationWindow {
|
||||||
currentDaemonAddress = localDaemonAddress
|
currentDaemonAddress = localDaemonAddress
|
||||||
|
|
||||||
console.log("initializing with daemon address: ", currentDaemonAddress)
|
console.log("initializing with daemon address: ", currentDaemonAddress)
|
||||||
currentWallet.initAsync(currentDaemonAddress, 0, persistentSettings.is_recovering, persistentSettings.restore_height);
|
currentWallet.initAsync(currentDaemonAddress, 0, persistentSettings.is_recovering, persistentSettings.is_recovering_from_device, persistentSettings.restore_height);
|
||||||
|
// save wallet keys in case wallet settings have been changed in the init
|
||||||
|
currentWallet.setPassword(walletPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
function walletPath() {
|
function walletPath() {
|
||||||
|
@ -1014,6 +1019,7 @@ ApplicationWindow {
|
||||||
property string payment_id
|
property string payment_id
|
||||||
property int restore_height : 0
|
property int restore_height : 0
|
||||||
property bool is_recovering : false
|
property bool is_recovering : false
|
||||||
|
property bool is_recovering_from_device : false
|
||||||
property bool customDecorations : true
|
property bool customDecorations : true
|
||||||
property string daemonFlags
|
property string daemonFlags
|
||||||
property int logLevel: 0
|
property int logLevel: 0
|
||||||
|
|
2
qml.qrc
2
qml.qrc
|
@ -85,9 +85,11 @@
|
||||||
<file>images/prevPage.png</file>
|
<file>images/prevPage.png</file>
|
||||||
<file>wizard/WizardOptions.qml</file>
|
<file>wizard/WizardOptions.qml</file>
|
||||||
<file>images/createWallet.png</file>
|
<file>images/createWallet.png</file>
|
||||||
|
<file>images/createWalletFromDevice.png</file>
|
||||||
<file>images/openAccount.png</file>
|
<file>images/openAccount.png</file>
|
||||||
<file>images/recoverWallet.png</file>
|
<file>images/recoverWallet.png</file>
|
||||||
<file>wizard/WizardCreateWallet.qml</file>
|
<file>wizard/WizardCreateWallet.qml</file>
|
||||||
|
<file>wizard/WizardCreateWalletFromDevice.qml</file>
|
||||||
<file>images/greyTriangle.png</file>
|
<file>images/greyTriangle.png</file>
|
||||||
<file>images/copyToClipboard.png</file>
|
<file>images/copyToClipboard.png</file>
|
||||||
<file>wizard/WizardPassword.qml</file>
|
<file>wizard/WizardPassword.qml</file>
|
||||||
|
|
|
@ -172,12 +172,18 @@ bool Wallet::store(const QString &path)
|
||||||
return m_walletImpl->store(path.toStdString());
|
return m_walletImpl->store(path.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wallet::init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
|
bool Wallet::init(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
|
||||||
{
|
{
|
||||||
qDebug() << "init non async";
|
qDebug() << "init non async";
|
||||||
if (isRecovering){
|
if (isRecovering){
|
||||||
qDebug() << "RESTORING";
|
qDebug() << "RESTORING";
|
||||||
m_walletImpl->setRecoveringFromSeed(true);
|
m_walletImpl->setRecoveringFromSeed(true);
|
||||||
|
}
|
||||||
|
if (isRecoveringFromDevice){
|
||||||
|
qDebug() << "RESTORING FROM DEVICE";
|
||||||
|
m_walletImpl->setRecoveringFromDevice(true);
|
||||||
|
}
|
||||||
|
if (isRecovering || isRecoveringFromDevice) {
|
||||||
m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
|
m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
|
||||||
}
|
}
|
||||||
m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
|
m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
|
||||||
|
@ -191,7 +197,7 @@ void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemon
|
||||||
m_daemonPassword = daemonPassword;
|
m_daemonPassword = daemonPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, quint64 restoreHeight)
|
void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
|
||||||
{
|
{
|
||||||
qDebug() << "initAsync: " + daemonAddress;
|
qDebug() << "initAsync: " + daemonAddress;
|
||||||
// Change status to disconnected if connected
|
// Change status to disconnected if connected
|
||||||
|
@ -201,7 +207,7 @@ void Wallet::initAsync(const QString &daemonAddress, quint64 upperTransactionLim
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<bool> future = QtConcurrent::run(this, &Wallet::init,
|
QFuture<bool> future = QtConcurrent::run(this, &Wallet::init,
|
||||||
daemonAddress, upperTransactionLimit, isRecovering, restoreHeight);
|
daemonAddress, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight);
|
||||||
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
QFutureWatcher<bool> * watcher = new QFutureWatcher<bool>();
|
||||||
|
|
||||||
connect(watcher, &QFutureWatcher<bool>::finished,
|
connect(watcher, &QFutureWatcher<bool>::finished,
|
||||||
|
|
|
@ -111,10 +111,10 @@ public:
|
||||||
Q_INVOKABLE bool store(const QString &path = "");
|
Q_INVOKABLE bool store(const QString &path = "");
|
||||||
|
|
||||||
//! initializes wallet
|
//! initializes wallet
|
||||||
Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, quint64 restoreHeight = 0);
|
Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0);
|
||||||
|
|
||||||
//! initializes wallet asynchronously
|
//! initializes wallet asynchronously
|
||||||
Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, quint64 restoreHeight = 0);
|
Q_INVOKABLE void initAsync(const QString &daemonAddress, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0);
|
||||||
|
|
||||||
// Set daemon rpc user/pass
|
// Set daemon rpc user/pass
|
||||||
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
|
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
|
||||||
|
|
|
@ -104,6 +104,20 @@ Wallet *WalletManager::createWalletFromKeys(const QString &path, const QString &
|
||||||
return m_currentWallet;
|
return m_currentWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString &password, NetworkType::Type nettype,
|
||||||
|
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
if (m_currentWallet) {
|
||||||
|
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
||||||
|
delete m_currentWallet;
|
||||||
|
m_currentWallet = NULL;
|
||||||
|
}
|
||||||
|
Monero::Wallet * w = m_pimpl->createWalletFromDevice(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype),
|
||||||
|
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString());
|
||||||
|
m_currentWallet = new Wallet(w);
|
||||||
|
return m_currentWallet;
|
||||||
|
}
|
||||||
|
|
||||||
QString WalletManager::closeWallet()
|
QString WalletManager::closeWallet()
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,6 +62,12 @@ public:
|
||||||
const QString &spendkey = "",
|
const QString &spendkey = "",
|
||||||
quint64 restoreHeight = 0);
|
quint64 restoreHeight = 0);
|
||||||
|
|
||||||
|
Q_INVOKABLE Wallet * createWalletFromDevice(const QString &path,
|
||||||
|
const QString &password,
|
||||||
|
NetworkType::Type nettype,
|
||||||
|
const QString &deviceName,
|
||||||
|
quint64 restoreHeight = 0,
|
||||||
|
const QString &subaddressLookahead = "");
|
||||||
/*!
|
/*!
|
||||||
* \brief closeWallet - closes current open wallet and frees memory
|
* \brief closeWallet - closes current open wallet and frees memory
|
||||||
* \return wallet address
|
* \return wallet address
|
||||||
|
|
123
wizard/WizardCreateWalletFromDevice.qml
Normal file
123
wizard/WizardCreateWalletFromDevice.qml
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
// Copyright (c) 2014-2018, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.2
|
||||||
|
import moneroComponents.WalletManager 1.0
|
||||||
|
import moneroComponents.Wallet 1.0
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import 'utils.js' as Utils
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
opacity: 0
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onOpacityChanged: visible = opacity !== 0
|
||||||
|
|
||||||
|
function onWizardRestarted() {
|
||||||
|
// reset account name field
|
||||||
|
uiItem.accountNameText = defaultAccountName
|
||||||
|
}
|
||||||
|
|
||||||
|
//! function called each time we display this page
|
||||||
|
|
||||||
|
function onPageOpened(settingsOblect) {
|
||||||
|
uiItem.checkNextButton()
|
||||||
|
uiItem.deviceNameDropdown.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPageClosed(settingsObject) {
|
||||||
|
settingsObject['account_name'] = uiItem.accountNameText
|
||||||
|
settingsObject['wallet_path'] = uiItem.walletPath
|
||||||
|
var restoreHeight = parseInt(uiItem.restoreHeight);
|
||||||
|
settingsObject['restore_height'] = isNaN(restoreHeight)? 0 : restoreHeight;
|
||||||
|
settingsObject['subaddress_lookahead'] = uiItem.subaddressLookahead;
|
||||||
|
settingsObject['deviceName'] = uiItem.deviceName;
|
||||||
|
var walletFullPath = wizard.createWalletPath(uiItem.walletPath,uiItem.accountNameText);
|
||||||
|
if (!wizard.walletPathValid(walletFullPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return createWalletFromDevice(settingsObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
//! function called each time we hide this page
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
function createWalletFromDevice(settingsObject) {
|
||||||
|
// TODO: create wallet in temporary filename and a) move it to the path specified by user after the final
|
||||||
|
// page submitted or b) delete it when program closed before reaching final page
|
||||||
|
|
||||||
|
// Always delete the wallet object before creating new - we could be stepping back from recovering wallet
|
||||||
|
if (typeof m_wallet !== 'undefined') {
|
||||||
|
walletManager.closeWallet()
|
||||||
|
console.log("deleting wallet")
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp_wallet_filename = oshelper.temporaryFilename();
|
||||||
|
console.log("Creating temporary wallet", tmp_wallet_filename)
|
||||||
|
var nettype = appWindow.persistentSettings.nettype;
|
||||||
|
var restoreHeight = settingsObject.restore_height;
|
||||||
|
var subaddressLookahead = settingsObject.subaddress_lookahead;
|
||||||
|
var deviceName = settingsObject.deviceName;
|
||||||
|
|
||||||
|
var wallet = walletManager.createWalletFromDevice(tmp_wallet_filename, "", nettype, deviceName, restoreHeight, subaddressLookahead);
|
||||||
|
|
||||||
|
var success = wallet.status === Wallet.Status_Ok;
|
||||||
|
if (success) {
|
||||||
|
m_wallet = wallet;
|
||||||
|
settingsObject['is_recovering_from_device'] = true;
|
||||||
|
settingsObject['tmp_wallet_filename'] = tmp_wallet_filename
|
||||||
|
} else {
|
||||||
|
console.log(wallet.errorString)
|
||||||
|
walletErrorDialog.text = wallet.errorString;
|
||||||
|
walletErrorDialog.open();
|
||||||
|
walletManager.closeWallet();
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
WizardManageWalletUI {
|
||||||
|
id: uiItem
|
||||||
|
titleText: qsTr("Create a new wallet from hardware device") + translationManager.emptyString
|
||||||
|
wordsTextItem.clipboardButtonVisible: false
|
||||||
|
wordsTextItem.tipTextVisible: false
|
||||||
|
restoreHeightVisible:true
|
||||||
|
recoverMode: false
|
||||||
|
recoverFromDevice: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
parent.wizardRestarted.connect(onWizardRestarted)
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,6 +54,7 @@ ColumnLayout {
|
||||||
"create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, daemonSettingsPage, finishPage ],
|
"create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, daemonSettingsPage, finishPage ],
|
||||||
"recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, daemonSettingsPage, finishPage ],
|
"recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, daemonSettingsPage, finishPage ],
|
||||||
"create_view_only_wallet" : [ createViewOnlyWalletPage, passwordPage ],
|
"create_view_only_wallet" : [ createViewOnlyWalletPage, passwordPage ],
|
||||||
|
"create_wallet_from_device" : [welcomePage, optionsPage, createWalletFromDevicePage, passwordPage, daemonSettingsPage, finishPage ],
|
||||||
|
|
||||||
}
|
}
|
||||||
property string currentPath: "create_wallet"
|
property string currentPath: "create_wallet"
|
||||||
|
@ -162,6 +163,16 @@ ColumnLayout {
|
||||||
rootItem.state = "wizard";
|
rootItem.state = "wizard";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openCreateWalletFromDevicePage() {
|
||||||
|
wizardRestarted();
|
||||||
|
print ("show create wallet from device page");
|
||||||
|
currentPath = "create_wallet_from_device"
|
||||||
|
pages = paths[currentPath]
|
||||||
|
wizard.nextButton.visible = true
|
||||||
|
// goto next page
|
||||||
|
switchPage(true);
|
||||||
|
}
|
||||||
|
|
||||||
function createWalletPath(folder_path,account_name){
|
function createWalletPath(folder_path,account_name){
|
||||||
|
|
||||||
// Remove trailing slash - (default on windows and mac)
|
// Remove trailing slash - (default on windows and mac)
|
||||||
|
@ -233,6 +244,7 @@ ColumnLayout {
|
||||||
appWindow.persistentSettings.auto_donations_amount = false //settings.auto_donations_amount
|
appWindow.persistentSettings.auto_donations_amount = false //settings.auto_donations_amount
|
||||||
appWindow.persistentSettings.restore_height = (isNaN(settings.restore_height))? 0 : settings.restore_height
|
appWindow.persistentSettings.restore_height = (isNaN(settings.restore_height))? 0 : settings.restore_height
|
||||||
appWindow.persistentSettings.is_recovering = (settings.is_recovering === undefined)? false : settings.is_recovering
|
appWindow.persistentSettings.is_recovering = (settings.is_recovering === undefined)? false : settings.is_recovering
|
||||||
|
appWindow.persistentSettings.is_recovering_from_device = (settings.is_recovering_from_device === undefined)? false : settings.is_recovering_from_device
|
||||||
}
|
}
|
||||||
|
|
||||||
// reading settings from persistent storage
|
// reading settings from persistent storage
|
||||||
|
@ -263,6 +275,7 @@ ColumnLayout {
|
||||||
onCreateWalletClicked: wizard.openCreateWalletPage()
|
onCreateWalletClicked: wizard.openCreateWalletPage()
|
||||||
onRecoveryWalletClicked: wizard.openRecoveryWalletPage()
|
onRecoveryWalletClicked: wizard.openRecoveryWalletPage()
|
||||||
onOpenWalletClicked: wizard.openOpenWalletPage();
|
onOpenWalletClicked: wizard.openOpenWalletPage();
|
||||||
|
onCreateWalletFromDeviceClicked: wizard.openCreateWalletFromDevicePage()
|
||||||
}
|
}
|
||||||
|
|
||||||
WizardCreateWallet {
|
WizardCreateWallet {
|
||||||
|
@ -283,6 +296,12 @@ ColumnLayout {
|
||||||
Layout.topMargin: wizardTopMargin
|
Layout.topMargin: wizardTopMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WizardCreateWalletFromDevice {
|
||||||
|
id: createWalletFromDevicePage
|
||||||
|
Layout.bottomMargin: wizardBottomMargin
|
||||||
|
Layout.topMargin: wizardTopMargin
|
||||||
|
}
|
||||||
|
|
||||||
WizardPassword {
|
WizardPassword {
|
||||||
id: passwordPage
|
id: passwordPage
|
||||||
Layout.bottomMargin: wizardBottomMargin
|
Layout.bottomMargin: wizardBottomMargin
|
||||||
|
|
|
@ -44,6 +44,7 @@ ColumnLayout {
|
||||||
property alias wordsTextItem : memoTextItem
|
property alias wordsTextItem : memoTextItem
|
||||||
property alias restoreHeight : restoreHeightItem.text
|
property alias restoreHeight : restoreHeightItem.text
|
||||||
property alias restoreHeightVisible: restoreHeightItem.visible
|
property alias restoreHeightVisible: restoreHeightItem.visible
|
||||||
|
property alias subaddressLookahead : subaddressLookaheadItem.text
|
||||||
property alias walletName : accountName.text
|
property alias walletName : accountName.text
|
||||||
property alias progressDotsModel : progressDots.model
|
property alias progressDotsModel : progressDots.model
|
||||||
property alias recoverFromKeysAddress: addressLine.text;
|
property alias recoverFromKeysAddress: addressLine.text;
|
||||||
|
@ -53,6 +54,10 @@ ColumnLayout {
|
||||||
property bool recoverMode: false
|
property bool recoverMode: false
|
||||||
// Recover form seed or keys
|
// Recover form seed or keys
|
||||||
property bool recoverFromSeedMode: true
|
property bool recoverFromSeedMode: true
|
||||||
|
// Recover form hardware device
|
||||||
|
property bool recoverFromDevice: false
|
||||||
|
property var deviceName: deviceNameModel.get(deviceNameDropdown.currentIndex).column2
|
||||||
|
property alias deviceNameDropdown: deviceNameDropdown
|
||||||
property int rowSpacing: 10
|
property int rowSpacing: 10
|
||||||
|
|
||||||
function checkFields(){
|
function checkFields(){
|
||||||
|
@ -215,7 +220,7 @@ ColumnLayout {
|
||||||
// Recover from seed
|
// Recover from seed
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: recoverFromSeed
|
id: recoverFromSeed
|
||||||
visible: !recoverMode || ( recoverMode && recoverFromSeedMode)
|
visible: !recoverFromDevice && (!recoverMode || ( recoverMode && recoverFromSeedMode))
|
||||||
WizardMemoTextInput {
|
WizardMemoTextInput {
|
||||||
id : memoTextItem
|
id : memoTextItem
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -303,9 +308,56 @@ ColumnLayout {
|
||||||
fontBold: false
|
fontBold: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subaddress lookahead
|
||||||
|
RowLayout {
|
||||||
|
visible: recoverFromDevice
|
||||||
|
LineEdit {
|
||||||
|
id: subaddressLookaheadItem
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth: 600 * scaleRatio
|
||||||
|
Layout.minimumWidth: 200 * scaleRatio
|
||||||
|
placeholderFontBold: true
|
||||||
|
placeholderFontFamily: "Arial"
|
||||||
|
placeholderColor: Style.legacy_placeholderFontColor
|
||||||
|
placeholderText: qsTr("Subaddress lookahead (optional): <major>:<minor>") + translationManager.emptyString
|
||||||
|
placeholderOpacity: 1.0
|
||||||
|
borderColor: Qt.rgba(0, 0, 0, 0.15)
|
||||||
|
backgroundColor: "white"
|
||||||
|
fontColor: "black"
|
||||||
|
fontBold: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device name
|
||||||
|
ColumnLayout {
|
||||||
|
visible: recoverFromDevice
|
||||||
|
Label {
|
||||||
|
Layout.topMargin: 20 * scaleRatio
|
||||||
|
fontFamily: "Arial"
|
||||||
|
fontColor: "#555555"
|
||||||
|
fontSize: 14 * scaleRatio
|
||||||
|
text: qsTr("Device name") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
ListModel {
|
||||||
|
id: deviceNameModel
|
||||||
|
ListElement { column1: qsTr("Ledger") ; column2: "Ledger"; }
|
||||||
|
// ListElement { column1: qsTr("Trezor") ; column2: "Trezor"; }
|
||||||
|
}
|
||||||
|
StandardDropdown {
|
||||||
|
id: deviceNameDropdown
|
||||||
|
dataModel: deviceNameModel
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 6
|
||||||
|
colorHeaderBackground: "black"
|
||||||
|
releasedColor: "#363636"
|
||||||
|
pressedColor: "#202020"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wallet store location
|
// Wallet store location
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
z: deviceNameDropdown.z - 1
|
||||||
Label {
|
Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 20 * scaleRatio
|
Layout.topMargin: 20 * scaleRatio
|
||||||
|
|
|
@ -37,9 +37,10 @@ ColumnLayout {
|
||||||
signal createWalletClicked()
|
signal createWalletClicked()
|
||||||
signal recoveryWalletClicked()
|
signal recoveryWalletClicked()
|
||||||
signal openWalletClicked()
|
signal openWalletClicked()
|
||||||
|
signal createWalletFromDeviceClicked()
|
||||||
opacity: 0
|
opacity: 0
|
||||||
visible: false
|
visible: false
|
||||||
property int buttonSize: (isMobile) ? 80 * scaleRatio : 190 * scaleRatio
|
property int buttonSize: (isMobile) ? 80 * scaleRatio : 140 * scaleRatio
|
||||||
property int buttonImageSize: (isMobile) ? buttonSize - 10 * scaleRatio : buttonSize - 30 * scaleRatio
|
property int buttonImageSize: (isMobile) ? buttonSize - 10 * scaleRatio : buttonSize - 30 * scaleRatio
|
||||||
|
|
||||||
function onPageClosed() {
|
function onPageClosed() {
|
||||||
|
@ -227,6 +228,51 @@ ColumnLayout {
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight
|
||||||
|
rowSpacing: 20 * scaleRatio
|
||||||
|
columnSpacing: 10 * scaleRatio
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredHeight: page.buttonSize
|
||||||
|
Layout.preferredWidth: page.buttonSize
|
||||||
|
radius: page.buttonSize
|
||||||
|
color: createWalletFromDeviceArea.containsMouse ? "#DBDBDB" : "#FFFFFF"
|
||||||
|
|
||||||
|
|
||||||
|
Image {
|
||||||
|
width: page.buttonImageSize
|
||||||
|
height: page.buttonImageSize
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
horizontalAlignment: Image.AlignRight
|
||||||
|
verticalAlignment: Image.AlignTop
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: "qrc:///images/createWalletFromDevice.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: createWalletFromDeviceArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
page.createWalletFromDeviceClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.preferredWidth: page.buttonSize
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 16 * scaleRatio
|
||||||
|
color: "#4A4949"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("Create a new wallet from hardware device") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|
Loading…
Reference in a new issue