1 // Copyright (c) 2019-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #if defined(HAVE_CONFIG_H)
6 #include <config/bitcoin-config.h>
7 #endif
8 
9 #include <external_signer.h>
10 #include <qt/createwalletdialog.h>
11 #include <qt/forms/ui_createwalletdialog.h>
12 
13 #include <qt/guiutil.h>
14 
15 #include <QPushButton>
16 
CreateWalletDialog(QWidget * parent)17 CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
18     QDialog(parent, GUIUtil::dialog_flags),
19     ui(new Ui::CreateWalletDialog)
20 {
21     ui->setupUi(this);
22     ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create"));
23     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
24     ui->wallet_name_line_edit->setFocus(Qt::ActiveWindowFocusReason);
25 
26     connect(ui->wallet_name_line_edit, &QLineEdit::textEdited, [this](const QString& text) {
27         ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
28     });
29 
30     connect(ui->encrypt_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) {
31         // Disable the disable_privkeys_checkbox and external_signer_checkbox when isEncryptWalletChecked is
32         // set to true, enable it when isEncryptWalletChecked is false.
33         ui->disable_privkeys_checkbox->setEnabled(!checked);
34 #ifdef ENABLE_EXTERNAL_SIGNER
35         ui->external_signer_checkbox->setEnabled(m_has_signers && !checked);
36 #endif
37         // When the disable_privkeys_checkbox is disabled, uncheck it.
38         if (!ui->disable_privkeys_checkbox->isEnabled()) {
39             ui->disable_privkeys_checkbox->setChecked(false);
40         }
41 
42         // When the external_signer_checkbox box is disabled, uncheck it.
43         if (!ui->external_signer_checkbox->isEnabled()) {
44             ui->external_signer_checkbox->setChecked(false);
45         }
46 
47     });
48 
49     connect(ui->external_signer_checkbox, &QCheckBox::toggled, [this](bool checked) {
50         ui->encrypt_wallet_checkbox->setEnabled(!checked);
51         ui->blank_wallet_checkbox->setEnabled(!checked);
52         ui->disable_privkeys_checkbox->setEnabled(!checked);
53         ui->descriptor_checkbox->setEnabled(!checked);
54 
55         // The external signer checkbox is only enabled when a device is detected.
56         // In that case it is checked by default. Toggling it restores the other
57         // options to their default.
58         ui->descriptor_checkbox->setChecked(checked);
59         ui->encrypt_wallet_checkbox->setChecked(false);
60         ui->disable_privkeys_checkbox->setChecked(checked);
61         // The blank check box is ambiguous. This flag is always true for a
62         // watch-only wallet, even though we immedidately fetch keys from the
63         // external signer.
64         ui->blank_wallet_checkbox->setChecked(checked);
65     });
66 
67     connect(ui->disable_privkeys_checkbox, &QCheckBox::toggled, [this](bool checked) {
68         // Disable the encrypt_wallet_checkbox when isDisablePrivateKeysChecked is
69         // set to true, enable it when isDisablePrivateKeysChecked is false.
70         ui->encrypt_wallet_checkbox->setEnabled(!checked);
71 
72         // Wallets without private keys start out blank
73         if (checked) {
74             ui->blank_wallet_checkbox->setChecked(true);
75         }
76 
77         // When the encrypt_wallet_checkbox is disabled, uncheck it.
78         if (!ui->encrypt_wallet_checkbox->isEnabled()) {
79             ui->encrypt_wallet_checkbox->setChecked(false);
80         }
81     });
82 
83     connect(ui->blank_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) {
84         if (!checked) {
85           ui->disable_privkeys_checkbox->setChecked(false);
86         }
87     });
88 
89 #ifndef USE_SQLITE
90         ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)"));
91         ui->descriptor_checkbox->setEnabled(false);
92         ui->descriptor_checkbox->setChecked(false);
93         ui->external_signer_checkbox->setEnabled(false);
94         ui->external_signer_checkbox->setChecked(false);
95 #endif
96 
97 #ifndef USE_BDB
98         ui->descriptor_checkbox->setEnabled(false);
99         ui->descriptor_checkbox->setChecked(true);
100 #endif
101 
102 #ifndef ENABLE_EXTERNAL_SIGNER
103         //: "External signing" means using devices such as hardware wallets.
104         ui->external_signer_checkbox->setToolTip(tr("Compiled without external signing support (required for external signing)"));
105         ui->external_signer_checkbox->setEnabled(false);
106         ui->external_signer_checkbox->setChecked(false);
107 #endif
108 
109 }
110 
~CreateWalletDialog()111 CreateWalletDialog::~CreateWalletDialog()
112 {
113     delete ui;
114 }
115 
setSigners(const std::vector<ExternalSigner> & signers)116 void CreateWalletDialog::setSigners(const std::vector<ExternalSigner>& signers)
117 {
118     m_has_signers = !signers.empty();
119     if (m_has_signers) {
120         ui->external_signer_checkbox->setEnabled(true);
121         ui->external_signer_checkbox->setChecked(true);
122         ui->encrypt_wallet_checkbox->setEnabled(false);
123         ui->encrypt_wallet_checkbox->setChecked(false);
124         // The order matters, because connect() is called when toggling a checkbox:
125         ui->blank_wallet_checkbox->setEnabled(false);
126         ui->blank_wallet_checkbox->setChecked(false);
127         ui->disable_privkeys_checkbox->setEnabled(false);
128         ui->disable_privkeys_checkbox->setChecked(true);
129         const std::string label = signers[0].m_name;
130         ui->wallet_name_line_edit->setText(QString::fromStdString(label));
131         ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
132     } else {
133         ui->external_signer_checkbox->setEnabled(false);
134     }
135 }
136 
walletName() const137 QString CreateWalletDialog::walletName() const
138 {
139     return ui->wallet_name_line_edit->text();
140 }
141 
isEncryptWalletChecked() const142 bool CreateWalletDialog::isEncryptWalletChecked() const
143 {
144     return ui->encrypt_wallet_checkbox->isChecked();
145 }
146 
isDisablePrivateKeysChecked() const147 bool CreateWalletDialog::isDisablePrivateKeysChecked() const
148 {
149     return ui->disable_privkeys_checkbox->isChecked();
150 }
151 
isMakeBlankWalletChecked() const152 bool CreateWalletDialog::isMakeBlankWalletChecked() const
153 {
154     return ui->blank_wallet_checkbox->isChecked();
155 }
156 
isDescriptorWalletChecked() const157 bool CreateWalletDialog::isDescriptorWalletChecked() const
158 {
159     return ui->descriptor_checkbox->isChecked();
160 }
161 
isExternalSignerChecked() const162 bool CreateWalletDialog::isExternalSignerChecked() const
163 {
164     return ui->external_signer_checkbox->isChecked();
165 }
166