Bitcoin ABC 0.32.4
P2P Digital Currency
walletview.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2016 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/walletview.h>
6
7#include <config.h> // For GetConfig
8#include <interfaces/node.h>
9#include <node/psbt.h>
10#include <node/transaction.h>
11#include <node/ui_interface.h>
12#include <policy/policy.h>
13#include <qt/addressbookpage.h>
15#include <qt/clientmodel.h>
16#include <qt/guiutil.h>
17#include <qt/optionsmodel.h>
18#include <qt/overviewpage.h>
19#include <qt/platformstyle.h>
21#include <qt/sendcoinsdialog.h>
24#include <qt/transactionview.h>
25#include <qt/walletmodel.h>
26#include <util/fs_helpers.h>
27#include <util/strencodings.h>
28
29#include <QAction>
30#include <QFileDialog>
31#include <QHBoxLayout>
32#include <QProgressDialog>
33#include <QPushButton>
34#include <QVBoxLayout>
35
36#include <fstream>
37
41
43 WalletModel *_walletModel, QWidget *parent)
44 : QStackedWidget(parent), clientModel(nullptr), walletModel(_walletModel),
45 platformStyle(_platformStyle) {
46 // Create tabs
48
49 transactionsPage = new QWidget(this);
50 QVBoxLayout *vbox = new QVBoxLayout();
51 QHBoxLayout *hbox_buttons = new QHBoxLayout();
53 vbox->addWidget(transactionView);
54 QPushButton *exportButton = new QPushButton(tr("&Export"), this);
55 exportButton->setToolTip(
56 tr("Export the data in the current tab to a file"));
58 exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
59 }
60 hbox_buttons->addStretch();
61 hbox_buttons->addWidget(exportButton);
62 vbox->addLayout(hbox_buttons);
63 transactionsPage->setLayout(vbox);
64
67
74
75 addWidget(overviewPage);
76 addWidget(transactionsPage);
77 addWidget(receiveCoinsPage);
78 addWidget(sendCoinsPage);
79
82 // Clicking on a transaction on the overview pre-selects the transaction on
83 // the transaction history page
85 static_cast<void (TransactionView::*)(const QModelIndex &)>(
87
90
93 // Highlight transaction after send
95 static_cast<void (TransactionView::*)(const uint256 &)>(
97
98 // Clicking on "Export" allows to export the transaction list
99 connect(exportButton, &QPushButton::clicked, transactionView,
101
102 // Pass through messages from sendCoinsPage
105 // Pass through messages from transactionView
108 connect(this, &WalletView::setPrivacy, overviewPage,
110
111 // Set the model properly.
113}
114
115WalletView::~WalletView() = default;
116
118 this->clientModel = _clientModel;
119
120 overviewPage->setClientModel(_clientModel);
121 sendCoinsPage->setClientModel(_clientModel);
122 if (walletModel) {
123 walletModel->setClientModel(_clientModel);
124 }
125}
126
128 this->walletModel = _walletModel;
129
130 // Put transaction list in tabs
131 transactionView->setModel(_walletModel);
132 overviewPage->setWalletModel(_walletModel);
133 receiveCoinsPage->setModel(_walletModel);
134 sendCoinsPage->setModel(_walletModel);
136 _walletModel ? _walletModel->getAddressTableModel() : nullptr);
138 _walletModel ? _walletModel->getAddressTableModel() : nullptr);
139
140 if (_walletModel) {
141 // Receive and pass through messages from wallet model
142 connect(_walletModel, &WalletModel::message, this,
144
145 // Handle changes in encryption status
146 connect(_walletModel, &WalletModel::encryptionStatusChanged, this,
149
150 // update HD status
151 Q_EMIT hdEnabledStatusChanged();
152
153 // Balloon pop-up for new transaction
154 connect(_walletModel->getTransactionTableModel(),
155 &TransactionTableModel::rowsInserted, this,
157
158 // Ask for passphrase if needed
159 connect(_walletModel, &WalletModel::requireUnlock, this,
161
162 // Show progress dialog
163 connect(_walletModel, &WalletModel::showProgress, this,
165 }
166}
167
168void WalletView::processNewTransaction(const QModelIndex &parent, int start,
169 int end) {
170 // Prevent balloon-spam when initial block download is in progress
171 if (!walletModel || !clientModel ||
173 return;
174 }
175
177 if (!ttm || ttm->processingQueuedTransactions()) {
178 return;
179 }
180
181 QString date = ttm->index(start, TransactionTableModel::Date, parent)
182 .data()
183 .toString();
184 qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
185 .data(Qt::EditRole)
186 .toULongLong();
187 QString type = ttm->index(start, TransactionTableModel::Type, parent)
188 .data()
189 .toString();
190 QModelIndex index = ttm->index(start, 0, parent);
191 QString address =
192 ttm->data(index, TransactionTableModel::AddressRole).toString();
193 QString label = GUIUtil::HtmlEscape(
194 ttm->data(index, TransactionTableModel::LabelRole).toString());
195
196 Q_EMIT incomingTransaction(
198 int64_t(amount) * SATOSHI, type, address, label,
200}
201
203 setCurrentWidget(overviewPage);
204}
205
207 setCurrentWidget(transactionsPage);
208}
209
211 setCurrentWidget(receiveCoinsPage);
212}
213
215 setCurrentWidget(sendCoinsPage);
216
217 if (!addr.isEmpty()) {
219 }
220}
221
223 // calls show() in showTab_SM()
224 SignVerifyMessageDialog *signVerifyMessageDialog =
226 signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
227 signVerifyMessageDialog->setModel(walletModel);
228 signVerifyMessageDialog->showTab_SM(true);
229
230 if (!addr.isEmpty()) {
231 signVerifyMessageDialog->setAddress_SM(addr);
232 }
233}
234
236 // calls show() in showTab_VM()
237 SignVerifyMessageDialog *signVerifyMessageDialog =
239 signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
240 signVerifyMessageDialog->setModel(walletModel);
241 signVerifyMessageDialog->showTab_VM(true);
242
243 if (!addr.isEmpty()) {
244 signVerifyMessageDialog->setAddress_VM(addr);
245 }
246}
247
249 QString filename = GUIUtil::getOpenFileName(
250 this, tr("Load Transaction Data"), QString(),
251 tr("Partially Signed Transaction (*.psbt)"), nullptr);
252 if (filename.isEmpty()) {
253 return;
254 }
255 if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) ==
257 Q_EMIT message(tr("Error"),
258 tr("PSBT file must be smaller than 100 MiB"),
260 return;
261 }
262 std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
263 std::vector<uint8_t> data;
264 data.assign(std::istream_iterator<uint8_t>{in}, {});
265
266 std::string error;
268 if (!DecodeRawPSBT(psbtx, MakeByteSpan(data), error)) {
269 Q_EMIT message(tr("Error"),
270 tr("Unable to decode PSBT file") + "\n" +
271 QString::fromStdString(error),
273 return;
274 }
275
277 bool complete = false;
278 PSBTAnalysis analysis = AnalyzePSBT(psbtx);
279 QMessageBox msgBox;
280 msgBox.setText("PSBT");
281 switch (analysis.next) {
284 msgBox.setInformativeText(
285 "PSBT is incomplete. Copy to clipboard for manual inspection?");
286 break;
287 case PSBTRole::SIGNER:
288 msgBox.setInformativeText(
289 "Transaction needs more signatures. Copy to clipboard?");
290 break;
293 complete = FinalizeAndExtractPSBT(psbtx, mtx);
294 if (complete) {
295 msgBox.setInformativeText(
296 tr("Would you like to send this transaction?"));
297 } else {
298 // The analyzer missed something, e.g. if there are
299 // final_scriptSig but with invalid signatures.
300 msgBox.setInformativeText(
301 tr("There was an unexpected problem processing the PSBT. "
302 "Copy to clipboard for manual inspection?"));
303 }
304 }
305
306 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
307 switch (msgBox.exec()) {
308 case QMessageBox::Yes: {
309 if (complete) {
310 std::string err_string;
312
314 *clientModel->node().context(), tx, err_string,
315 DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true,
316 /* wait_callback */ false);
317 if (result == TransactionError::OK) {
318 Q_EMIT message(tr("Success"),
319 tr("Broadcasted transaction successfully."),
322 } else {
323 Q_EMIT message(tr("Error"),
324 QString::fromStdString(err_string),
326 }
327 } else {
328 // Serialize the PSBT
330 ssTx << psbtx;
331 GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
332 Q_EMIT message(tr("PSBT copied"), "Copied to clipboard",
334 return;
335 }
336 }
337 case QMessageBox::Cancel:
338 break;
339 default:
340 assert(false);
341 }
342}
343
345 return sendCoinsPage->handlePaymentRequest(recipient);
346}
347
350}
351
354}
355
357 if (!walletModel) {
358 return;
359 }
361 dlg->setModel(walletModel);
362 connect(dlg, &QDialog::finished, this,
365}
366
368 QString filename =
369 GUIUtil::getSaveFileName(this, tr("Backup Wallet"), QString(),
370 tr("Wallet Data (*.dat)"), nullptr);
371
372 if (filename.isEmpty()) {
373 return;
374 }
375
376 if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
377 Q_EMIT message(
378 tr("Backup Failed"),
379 tr("There was an error trying to save the wallet data to %1.")
380 .arg(filename),
382 } else {
383 Q_EMIT message(
384 tr("Backup Successful"),
385 tr("The wallet data was successfully saved to %1.").arg(filename),
387 }
388}
389
392 dlg->setModel(walletModel);
394}
395
397 if (!walletModel) {
398 return;
399 }
400
401 // Unlock wallet when requested by wallet model
405 // A modal dialog must be synchronous here as expected
406 // in the WalletModel::requestUnlock() function.
407 dlg.exec();
408 }
409}
410
412 if (!walletModel) {
413 return;
414 }
415
417}
418
420 if (!walletModel) {
421 return;
422 }
423
425}
426
427void WalletView::showProgress(const QString &title, int nProgress) {
428 if (nProgress == 0) {
429 progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100);
431 progressDialog->setWindowModality(Qt::ApplicationModal);
432 progressDialog->setMinimumDuration(0);
433 progressDialog->setAutoClose(false);
434 progressDialog->setValue(0);
435 } else if (nProgress == 100) {
436 if (progressDialog) {
437 progressDialog->close();
438 progressDialog->deleteLater();
439 progressDialog = nullptr;
440 }
441 } else if (progressDialog) {
442 if (progressDialog->wasCanceled()) {
444 } else {
445 progressDialog->setValue(nProgress);
446 }
447 }
448}
449
452}
static constexpr Amount SATOSHI
Definition: amount.h:143
Widget that shows a list of sending or receiving addresses.
@ ForEditing
Open address book for editing.
void setModel(AddressTableModel *model)
Multifunctional dialog to ask for passphrases.
void setModel(WalletModel *model)
@ Unlock
Ask passphrase and unlock.
@ Encrypt
Ask passphrase twice and encrypt.
@ ChangePass
Ask old passphrase + new passphrase twice.
@ MSG_INFORMATION
Predefined combinations for certain default usage cases.
Definition: ui_interface.h:72
@ MODAL
Force blocking, modal message box dialog (not just OS notification)
Definition: ui_interface.h:66
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
A mutable version of CTransaction.
Definition: transaction.h:274
Model for Bitcoin network client.
Definition: clientmodel.h:43
interfaces::Node & node() const
Definition: clientmodel.h:60
std::string str() const
Definition: streams.h:195
int getDisplayUnit() const
Definition: optionsmodel.h:97
Overview ("home") page widget.
Definition: overviewpage.h:28
void setWalletModel(WalletModel *walletModel)
void setClientModel(ClientModel *clientModel)
void transactionClicked(const QModelIndex &index)
void outOfSyncWarningClicked()
void showOutOfSyncWarning(bool fShow)
void setPrivacy(bool privacy)
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
bool getImagesOnButtons() const
Definition: platformstyle.h:20
Dialog for requesting payment of bitcoins.
void setModel(WalletModel *model)
Dialog for sending bitcoins.
void setClientModel(ClientModel *clientModel)
void setModel(WalletModel *model)
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
void setAddress(const QString &address)
void message(const QString &title, const QString &message, unsigned int style)
void coinsSent(const uint256 &txid)
void setAddress_SM(const QString &address)
void setModel(WalletModel *model)
void setAddress_VM(const QString &address)
UI model for the transaction table of a wallet.
@ LabelRole
Label of address related to transaction.
@ AddressRole
Address of transaction.
QVariant data(const QModelIndex &index, int role) const override
bool processingQueuedTransactions() const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Widget showing the transaction list for a wallet, including a filter row.
void setModel(WalletModel *model)
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
void focusTransaction(const QModelIndex &)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
void showProgress(const QString &title, int nProgress)
void message(const QString &title, const QString &message, unsigned int style)
void setClientModel(ClientModel *client_model)
Definition: walletmodel.cpp:57
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
EncryptionStatus getEncryptionStatus() const
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
void requireUnlock()
void encryptionStatusChanged()
QString getWalletName() const
TransactionTableModel * getTransactionTableModel()
const PlatformStyle * platformStyle
Definition: walletview.h:74
void gotoHistoryPage()
Switch to history (transactions) page.
Definition: walletview.cpp:206
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
Definition: walletview.cpp:235
void setWalletModel(WalletModel *walletModel)
Set the wallet model.
Definition: walletview.cpp:127
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: walletview.cpp:344
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
Definition: walletview.cpp:214
void incomingTransaction(const QString &date, int unit, const Amount amount, const QString &type, const QString &address, const QString &label, const QString &walletName)
Notify that a new transaction appeared.
void changePassphrase()
Change encrypted wallet passphrase.
Definition: walletview.cpp:390
QProgressDialog * progressDialog
Definition: walletview.h:73
SendCoinsDialog * sendCoinsPage
Definition: walletview.h:67
OverviewPage * overviewPage
Definition: walletview.h:64
void setClientModel(ClientModel *clientModel)
Set the client model.
Definition: walletview.cpp:117
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
void gotoReceiveCoinsPage()
Switch to receive coins page.
Definition: walletview.cpp:210
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
Definition: walletview.cpp:222
QWidget * transactionsPage
Definition: walletview.h:65
void usedSendingAddresses()
Show used sending addresses.
Definition: walletview.cpp:411
ReceiveCoinsDialog * receiveCoinsPage
Definition: walletview.h:66
void encryptWallet()
Encrypt the wallet.
Definition: walletview.cpp:356
TransactionView * transactionView
Definition: walletview.h:71
WalletView(const PlatformStyle *platformStyle, WalletModel *walletModel, QWidget *parent)
Definition: walletview.cpp:42
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
Definition: walletview.cpp:427
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
AddressBookPage * usedReceivingAddressesPage
Definition: walletview.h:69
void backupWallet()
Backup the wallet.
Definition: walletview.cpp:367
ClientModel * clientModel
Definition: walletview.h:61
void gotoLoadPSBT()
Load Partially Signed Bitcoin Transaction.
Definition: walletview.cpp:248
void requestedSyncWarningInfo()
User has requested more information about the out of sync state.
Definition: walletview.cpp:450
AddressBookPage * usedSendingAddressesPage
Definition: walletview.h:68
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
Definition: walletview.cpp:396
WalletModel * walletModel
Definition: walletview.h:62
void gotoOverviewPage()
Switch to overview (home) page.
Definition: walletview.cpp:202
void usedReceivingAddresses()
Show used receiving addresses.
Definition: walletview.cpp:419
void transactionClicked()
WalletModel * getWalletModel()
Definition: walletview.h:48
void updateEncryptionStatus()
Re-emit encryption status signal.
Definition: walletview.cpp:352
void hdEnabledStatusChanged()
HD-Enabled status of wallet changed (only possible during startup)
void coinsSent()
void setPrivacy(bool privacy)
void processNewTransaction(const QModelIndex &parent, int start, int end)
Show incoming transaction notification for new transactions.
Definition: walletview.cpp:168
void showOutOfSyncWarning(bool fShow)
Definition: walletview.cpp:348
void encryptionStatusChanged()
Encryption status of wallet changed.
virtual node::NodeContext * context()
Get and set internal node context.
Definition: node.h:265
virtual bool isInitialBlockDownload()=0
Is initial block download.
virtual void abortRescan()=0
Abort a rescan.
virtual bool backupWallet(const std::string &filename)=0
Back up wallet.
256-bit opaque blob.
Definition: uint256.h:129
TransactionError
Definition: error.h:22
std::streampos GetFileSize(const char *path, std::streamsize max)
Get the size of a file by scanning it.
Definition: fs_helpers.cpp:120
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:256
void ShowModalDialogAsynchronously(QDialog *dialog)
Shows a QDialog instance asynchronously, and deletes it on close.
Definition: guiutil.cpp:1000
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:959
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:347
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:310
void bringToFront(QWidget *w)
Definition: guiutil.cpp:393
void setClipboard(const QString &str)
Definition: guiutil.cpp:782
PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
Provides helpful miscellaneous information about where a PSBT is in the signing workflow.
Definition: psbt.cpp:16
TransactionError BroadcastTransaction(const NodeContext &node, const CTransactionRef tx, std::string &err_string, const Amount max_tx_fee, bool relay, bool wait_callback)
Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
Definition: transaction.cpp:37
static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE
Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
Definition: transaction.h:33
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:316
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
Definition: psbt.cpp:247
bool DecodeRawPSBT(PartiallySignedTransaction &psbt, Span< const std::byte > tx_data, std::string &error)
Decode a raw (binary blob) PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:306
const std::streamsize MAX_FILE_SIZE_PSBT
Definition: psbt.h:41
@ SER_NETWORK
Definition: serialize.h:154
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:302
A version of CTransaction with the PSBT format.
Definition: psbt.h:334
Holds the results of AnalyzePSBT (miscellaneous information about a PSBT)
Definition: psbt.h:35
PSBTRole next
Which of the BIP 174 roles needs to handle the transaction next.
Definition: psbt.h:45
std::string EncodeBase64(Span< const uint8_t > input)
assert(!tx.IsCoinBase())
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11