Bitcoin Core 31.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
walletframe.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-present 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#include <qt/walletframe.h>
6
7#include <node/interface_ui.h>
8#include <psbt.h>
9#include <qt/guiutil.h>
10#include <qt/overviewpage.h>
12#include <qt/walletmodel.h>
13#include <qt/walletview.h>
14#include <util/fs.h>
15#include <util/fs_helpers.h>
16
17#include <cassert>
18#include <fstream>
19#include <string>
20
21#include <QApplication>
22#include <QClipboard>
23#include <QGroupBox>
24#include <QHBoxLayout>
25#include <QLabel>
26#include <QPushButton>
27#include <QVBoxLayout>
28
29WalletFrame::WalletFrame(const PlatformStyle* _platformStyle, QWidget* parent)
30 : QFrame(parent),
31 platformStyle(_platformStyle),
33{
34 // Leave HBox hook for adding a list view later
35 QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
36 setContentsMargins(0,0,0,0);
37 walletStack = new QStackedWidget(this);
38 walletFrameLayout->setContentsMargins(0,0,0,0);
39 walletFrameLayout->addWidget(walletStack);
40
41 // hbox for no wallet
42 QGroupBox* no_wallet_group = new QGroupBox(walletStack);
43 QVBoxLayout* no_wallet_layout = new QVBoxLayout(no_wallet_group);
44
45 QLabel *noWallet = new QLabel(tr("No wallet has been loaded.\nGo to File > Open Wallet to load a wallet.\n- OR -"));
46 noWallet->setAlignment(Qt::AlignCenter);
47 no_wallet_layout->addWidget(noWallet, 0, Qt::AlignHCenter | Qt::AlignBottom);
48
49 // A button for create wallet dialog
50 QPushButton* create_wallet_button = new QPushButton(tr("Create a new wallet"), walletStack);
51 connect(create_wallet_button, &QPushButton::clicked, this, &WalletFrame::createWalletButtonClicked);
52 no_wallet_layout->addWidget(create_wallet_button, 0, Qt::AlignHCenter | Qt::AlignTop);
53 no_wallet_group->setLayout(no_wallet_layout);
54
55 walletStack->addWidget(no_wallet_group);
56}
57
59
61{
62 this->clientModel = _clientModel;
63
64 for (auto i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) {
65 i.value()->setClientModel(_clientModel);
66 }
67}
68
70{
71 if (!clientModel) return false;
72
73 if (mapWalletViews.contains(walletView->getWalletModel())) return false;
74
75 walletView->setClientModel(clientModel);
77
78 WalletView* current_wallet_view = currentWalletView();
79 if (current_wallet_view) {
80 walletView->setCurrentIndex(current_wallet_view->currentIndex());
81 } else {
82 walletView->gotoOverviewPage();
83 }
84
85 walletStack->addWidget(walletView);
86 mapWalletViews[walletView->getWalletModel()] = walletView;
87
88 return true;
89}
90
92{
93 if (!mapWalletViews.contains(wallet_model)) return;
94
95 // Stop the effect of hidden widgets on the size hint of the shown one in QStackedWidget.
96 WalletView* view_about_to_hide = currentWalletView();
97 if (view_about_to_hide) {
98 QSizePolicy sp = view_about_to_hide->sizePolicy();
99 sp.setHorizontalPolicy(QSizePolicy::Ignored);
100 view_about_to_hide->setSizePolicy(sp);
101 }
102
103 WalletView *walletView = mapWalletViews.value(wallet_model);
104 assert(walletView);
105
106 // Set or restore the default QSizePolicy which could be set to QSizePolicy::Ignored previously.
107 QSizePolicy sp = walletView->sizePolicy();
108 sp.setHorizontalPolicy(QSizePolicy::Preferred);
109 walletView->setSizePolicy(sp);
110 walletView->updateGeometry();
111
112 walletStack->setCurrentWidget(walletView);
113
114 Q_EMIT currentWalletSet();
115}
116
118{
119 if (!mapWalletViews.contains(wallet_model)) return;
120
121 WalletView *walletView = mapWalletViews.take(wallet_model);
122 walletStack->removeWidget(walletView);
123 delete walletView;
124}
125
127{
128 QMap<WalletModel*, WalletView*>::const_iterator i;
129 for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
130 walletStack->removeWidget(i.value());
131 mapWalletViews.clear();
132}
133
135{
136 WalletView *walletView = currentWalletView();
137 if (!walletView)
138 return false;
139
140 return walletView->handlePaymentRequest(recipient);
141}
142
144{
145 bOutOfSync = fShow;
146 QMap<WalletModel*, WalletView*>::const_iterator i;
147 for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
148 i.value()->showOutOfSyncWarning(fShow);
149}
150
152{
153 QMap<WalletModel*, WalletView*>::const_iterator i;
154 for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
155 i.value()->gotoOverviewPage();
156}
157
159{
160 QMap<WalletModel*, WalletView*>::const_iterator i;
161 for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
162 i.value()->gotoHistoryPage();
163}
164
166{
167 QMap<WalletModel*, WalletView*>::const_iterator i;
168 for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
169 i.value()->gotoReceiveCoinsPage();
170}
171
173{
174 QMap<WalletModel*, WalletView*>::const_iterator i;
175 for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
176 i.value()->gotoSendCoinsPage(addr);
177}
178
180{
181 WalletView *walletView = currentWalletView();
182 if (walletView)
183 walletView->gotoSignMessageTab(addr);
184}
185
187{
188 WalletView *walletView = currentWalletView();
189 if (walletView)
190 walletView->gotoVerifyMessageTab(addr);
191}
192
193void WalletFrame::gotoLoadPSBT(bool from_clipboard)
194{
195 std::vector<unsigned char> data;
196
197 if (from_clipboard) {
198 std::string raw = QApplication::clipboard()->text().toStdString();
199 auto result = DecodeBase64(raw);
200 if (!result) {
201 Q_EMIT message(tr("Error"), tr("Unable to decode PSBT from clipboard (invalid base64)"), CClientUIInterface::MSG_ERROR);
202 return;
203 }
204 data = std::move(*result);
205 } else {
206 QString filename = GUIUtil::getOpenFileName(this,
207 tr("Load Transaction Data"), QString(),
208 tr("Partially Signed Transaction (*.psbt)"), nullptr);
209 if (filename.isEmpty()) return;
210 if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) == MAX_FILE_SIZE_PSBT) {
211 Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR);
212 return;
213 }
214 std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
215 data.assign(std::istreambuf_iterator<char>{in}, {});
216
217 // Some psbt files may be base64 strings in the file rather than binary data
218 std::string b64_str{data.begin(), data.end()};
219 b64_str.erase(b64_str.find_last_not_of(" \t\n\r\f\v") + 1); // Trim trailing whitespace
220 auto b64_dec = DecodeBase64(b64_str);
221 if (b64_dec.has_value()) {
222 data = b64_dec.value();
223 }
224 }
225
226 std::string error;
228 if (!DecodeRawPSBT(psbtx, MakeByteSpan(data), error)) {
229 Q_EMIT message(tr("Error"), tr("Unable to decode PSBT") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR);
230 return;
231 }
232
233 auto dlg = new PSBTOperationsDialog(this, currentWalletModel(), clientModel);
234 dlg->openWithPSBT(psbtx);
236}
237
239{
240 WalletView *walletView = currentWalletView();
241 if (walletView)
242 walletView->encryptWallet();
243}
244
246{
247 WalletView *walletView = currentWalletView();
248 if (walletView)
249 walletView->backupWallet();
250}
251
253{
254 WalletView *walletView = currentWalletView();
255 if (walletView)
256 walletView->changePassphrase();
257}
258
260{
261 WalletView *walletView = currentWalletView();
262 if (walletView)
263 walletView->unlockWallet();
264}
265
267{
268 WalletView *walletView = currentWalletView();
269 if (walletView)
270 walletView->usedSendingAddresses();
271}
272
274{
275 WalletView *walletView = currentWalletView();
276 if (walletView)
277 walletView->usedReceivingAddresses();
278}
279
281{
282 return qobject_cast<WalletView*>(walletStack->currentWidget());
283}
284
286{
287 WalletView* wallet_view = currentWalletView();
288 return wallet_view ? wallet_view->getWalletModel() : nullptr;
289}
Model for Bitcoin network client.
Definition clientmodel.h:57
Overview ("home") page widget.
Dialog showing transaction details.
void removeAllWallets()
void currentWalletSet()
bool addView(WalletView *walletView)
void changePassphrase()
Change encrypted wallet passphrase.
WalletModel * currentWalletModel() const
void gotoHistoryPage()
Switch to history (transactions) page.
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
WalletView * currentWalletView() const
void gotoOverviewPage()
Switch to overview (home) page.
ClientModel * clientModel
Definition walletframe.h:56
const PlatformStyle * platformStyle
Definition walletframe.h:61
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
void removeWallet(WalletModel *wallet_model)
void setClientModel(ClientModel *clientModel)
bool bOutOfSync
Definition walletframe.h:59
void backupWallet()
Backup the wallet.
QStackedWidget * walletStack
Definition walletframe.h:55
void usedSendingAddresses()
Show used sending addresses.
void createWalletButtonClicked()
void encryptWallet()
Encrypt the wallet.
QSize sizeHint() const override
Definition walletframe.h:47
void usedReceivingAddresses()
Show used receiving addresses.
void message(const QString &title, const QString &message, unsigned int style)
const QSize m_size_hint
Definition walletframe.h:63
void setCurrentWallet(WalletModel *wallet_model)
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
QMap< WalletModel *, WalletView * > mapWalletViews
Definition walletframe.h:57
void gotoLoadPSBT(bool from_clipboard=false)
Load Partially Signed Bitcoin Transaction.
WalletFrame(const PlatformStyle *platformStyle, QWidget *parent)
void showOutOfSyncWarning(bool fShow)
void gotoReceiveCoinsPage()
Switch to receive coins page.
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
Interface to Bitcoin wallet from Qt view code.
Definition walletmodel.h:49
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
void changePassphrase()
Change encrypted wallet passphrase.
void setClientModel(ClientModel *clientModel)
Set the client model.
WalletModel * getWalletModel() const noexcept
Definition walletview.h:46
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
void usedSendingAddresses()
Show used sending addresses.
void encryptWallet()
Encrypt the wallet.
void backupWallet()
Backup the wallet.
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
void gotoOverviewPage()
Switch to overview (home) page.
void usedReceivingAddresses()
Show used receiving addresses.
void showOutOfSyncWarning(bool fShow)
std::streampos GetFileSize(const char *path, std::streamsize max)
Get the size of a file by scanning it.
void ShowModalDialogAsynchronously(QDialog *dialog)
Shows a QDialog instance asynchronously, and deletes it on close.
Definition guiutil.cpp:978
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
Definition guiutil.cpp:353
bool DecodeRawPSBT(PartiallySignedTransaction &psbt, std::span< const std::byte > tx_data, std::string &error)
Decode a raw (binary blob) PSBT into a PartiallySignedTransaction.
Definition psbt.cpp:618
const std::streamsize MAX_FILE_SIZE_PSBT
Definition psbt.h:77
auto MakeByteSpan(const V &v) noexcept
Definition span.h:84
A version of CTransaction with the PSBT format.
Definition psbt.h:1139
std::optional< std::vector< unsigned char > > DecodeBase64(std::string_view str)
assert(!tx.IsCoinBase())