Bitcoin ABC 0.30.5
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 <QActionGroup>
31#include <QFileDialog>
32#include <QHBoxLayout>
33#include <QProgressDialog>
34#include <QPushButton>
35#include <QVBoxLayout>
36
37#include <fstream>
38
42
44 WalletModel *_walletModel, QWidget *parent)
45 : QStackedWidget(parent), clientModel(nullptr), walletModel(_walletModel),
46 platformStyle(_platformStyle) {
47 // Create tabs
49
50 transactionsPage = new QWidget(this);
51 QVBoxLayout *vbox = new QVBoxLayout();
52 QHBoxLayout *hbox_buttons = new QHBoxLayout();
54 vbox->addWidget(transactionView);
55 QPushButton *exportButton = new QPushButton(tr("&Export"), this);
56 exportButton->setToolTip(
57 tr("Export the data in the current tab to a file"));
59 exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
60 }
61 hbox_buttons->addStretch();
62 hbox_buttons->addWidget(exportButton);
63 vbox->addLayout(hbox_buttons);
64 transactionsPage->setLayout(vbox);
65
68
75
76 addWidget(overviewPage);
77 addWidget(transactionsPage);
78 addWidget(receiveCoinsPage);
79 addWidget(sendCoinsPage);
80
83 // Clicking on a transaction on the overview pre-selects the transaction on
84 // the transaction history page
86 static_cast<void (TransactionView::*)(const QModelIndex &)>(
88
91
94 // Highlight transaction after send
96 static_cast<void (TransactionView::*)(const uint256 &)>(
98
99 // Clicking on "Export" allows to export the transaction list
100 connect(exportButton, &QPushButton::clicked, transactionView,
102
103 // Pass through messages from sendCoinsPage
106 // Pass through messages from transactionView
109 connect(this, &WalletView::setPrivacy, overviewPage,
111
112 // Set the model properly.
114}
115
117
119 this->clientModel = _clientModel;
120
121 overviewPage->setClientModel(_clientModel);
122 sendCoinsPage->setClientModel(_clientModel);
123 if (walletModel) {
124 walletModel->setClientModel(_clientModel);
125 }
126}
127
129 this->walletModel = _walletModel;
130
131 // Put transaction list in tabs
132 transactionView->setModel(_walletModel);
133 overviewPage->setWalletModel(_walletModel);
134 receiveCoinsPage->setModel(_walletModel);
135 sendCoinsPage->setModel(_walletModel);
137 _walletModel ? _walletModel->getAddressTableModel() : nullptr);
139 _walletModel ? _walletModel->getAddressTableModel() : nullptr);
140
141 if (_walletModel) {
142 // Receive and pass through messages from wallet model
143 connect(_walletModel, &WalletModel::message, this,
145
146 // Handle changes in encryption status
147 connect(_walletModel, &WalletModel::encryptionStatusChanged, this,
150
151 // update HD status
152 Q_EMIT hdEnabledStatusChanged();
153
154 // Balloon pop-up for new transaction
155 connect(_walletModel->getTransactionTableModel(),
156 &TransactionTableModel::rowsInserted, this,
158
159 // Ask for passphrase if needed
160 connect(_walletModel, &WalletModel::requireUnlock, this,
162
163 // Show progress dialog
164 connect(_walletModel, &WalletModel::showProgress, this,
166 }
167}
168
169void WalletView::processNewTransaction(const QModelIndex &parent, int start,
170 int end) {
171 // Prevent balloon-spam when initial block download is in progress
172 if (!walletModel || !clientModel ||
174 return;
175 }
176
178 if (!ttm || ttm->processingQueuedTransactions()) {
179 return;
180 }
181
182 QString date = ttm->index(start, TransactionTableModel::Date, parent)
183 .data()
184 .toString();
185 qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
186 .data(Qt::EditRole)
187 .toULongLong();
188 QString type = ttm->index(start, TransactionTableModel::Type, parent)
189 .data()
190 .toString();
191 QModelIndex index = ttm->index(start, 0, parent);
192 QString address =
193 ttm->data(index, TransactionTableModel::AddressRole).toString();
194 QString label = GUIUtil::HtmlEscape(
195 ttm->data(index, TransactionTableModel::LabelRole).toString());
196
197 Q_EMIT incomingTransaction(
199 int64_t(amount) * SATOSHI, type, address, label,
201}
202
204 setCurrentWidget(overviewPage);
205}
206
208 setCurrentWidget(transactionsPage);
209}
210
212 setCurrentWidget(receiveCoinsPage);
213}
214
216 setCurrentWidget(sendCoinsPage);
217
218 if (!addr.isEmpty()) {
220 }
221}
222
224 // calls show() in showTab_SM()
225 SignVerifyMessageDialog *signVerifyMessageDialog =
227 signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
228 signVerifyMessageDialog->setModel(walletModel);
229 signVerifyMessageDialog->showTab_SM(true);
230
231 if (!addr.isEmpty()) {
232 signVerifyMessageDialog->setAddress_SM(addr);
233 }
234}
235
237 // calls show() in showTab_VM()
238 SignVerifyMessageDialog *signVerifyMessageDialog =
240 signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
241 signVerifyMessageDialog->setModel(walletModel);
242 signVerifyMessageDialog->showTab_VM(true);
243
244 if (!addr.isEmpty()) {
245 signVerifyMessageDialog->setAddress_VM(addr);
246 }
247}
248
250 QString filename = GUIUtil::getOpenFileName(
251 this, tr("Load Transaction Data"), QString(),
252 tr("Partially Signed Transaction (*.psbt)"), nullptr);
253 if (filename.isEmpty()) {
254 return;
255 }
256 if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) ==
258 Q_EMIT message(tr("Error"),
259 tr("PSBT file must be smaller than 100 MiB"),
261 return;
262 }
263 std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
264 std::vector<uint8_t> data;
265 data.assign(std::istream_iterator<uint8_t>{in}, {});
266
267 std::string error;
269 if (!DecodeRawPSBT(psbtx, MakeByteSpan(data), error)) {
270 Q_EMIT message(tr("Error"),
271 tr("Unable to decode PSBT file") + "\n" +
272 QString::fromStdString(error),
274 return;
275 }
276
278 bool complete = false;
279 PSBTAnalysis analysis = AnalyzePSBT(psbtx);
280 QMessageBox msgBox;
281 msgBox.setText("PSBT");
282 switch (analysis.next) {
285 msgBox.setInformativeText(
286 "PSBT is incomplete. Copy to clipboard for manual inspection?");
287 break;
288 case PSBTRole::SIGNER:
289 msgBox.setInformativeText(
290 "Transaction needs more signatures. Copy to clipboard?");
291 break;
294 complete = FinalizeAndExtractPSBT(psbtx, mtx);
295 if (complete) {
296 msgBox.setInformativeText(
297 tr("Would you like to send this transaction?"));
298 } else {
299 // The analyzer missed something, e.g. if there are
300 // final_scriptSig but with invalid signatures.
301 msgBox.setInformativeText(
302 tr("There was an unexpected problem processing the PSBT. "
303 "Copy to clipboard for manual inspection?"));
304 }
305 }
306
307 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
308 switch (msgBox.exec()) {
309 case QMessageBox::Yes: {
310 if (complete) {
311 std::string err_string;
313
315 *clientModel->node().context(), tx, err_string,
316 DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true,
317 /* wait_callback */ false);
318 if (result == TransactionError::OK) {
319 Q_EMIT message(tr("Success"),
320 tr("Broadcasted transaction successfully."),
323 } else {
324 Q_EMIT message(tr("Error"),
325 QString::fromStdString(err_string),
327 }
328 } else {
329 // Serialize the PSBT
331 ssTx << psbtx;
332 GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
333 Q_EMIT message(tr("PSBT copied"), "Copied to clipboard",
335 return;
336 }
337 }
338 case QMessageBox::Cancel:
339 break;
340 default:
341 assert(false);
342 }
343}
344
346 return sendCoinsPage->handlePaymentRequest(recipient);
347}
348
351}
352
355}
356
358 if (!walletModel) {
359 return;
360 }
363 dlg.exec();
364
366}
367
369 QString filename =
370 GUIUtil::getSaveFileName(this, tr("Backup Wallet"), QString(),
371 tr("Wallet Data (*.dat)"), nullptr);
372
373 if (filename.isEmpty()) {
374 return;
375 }
376
377 if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
378 Q_EMIT message(
379 tr("Backup Failed"),
380 tr("There was an error trying to save the wallet data to %1.")
381 .arg(filename),
383 } else {
384 Q_EMIT message(
385 tr("Backup Successful"),
386 tr("The wallet data was successfully saved to %1.").arg(filename),
388 }
389}
390
394 dlg.exec();
395}
396
398 if (!walletModel) {
399 return;
400 }
401
402 // Unlock wallet when requested by wallet model
406 dlg.exec();
407 }
408}
409
411 if (!walletModel) {
412 return;
413 }
414
416}
417
419 if (!walletModel) {
420 return;
421 }
422
424}
425
426void WalletView::showProgress(const QString &title, int nProgress) {
427 if (nProgress == 0) {
428 progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100);
430 progressDialog->setWindowModality(Qt::ApplicationModal);
431 progressDialog->setMinimumDuration(0);
432 progressDialog->setAutoClose(false);
433 progressDialog->setValue(0);
434 } else if (nProgress == 100) {
435 if (progressDialog) {
436 progressDialog->close();
437 progressDialog->deleteLater();
438 progressDialog = nullptr;
439 }
440 } else if (progressDialog) {
441 if (progressDialog->wasCanceled()) {
443 } else {
444 progressDialog->setValue(nProgress);
445 }
446 }
447}
448
451}
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:71
@ MODAL
Force blocking, modal message box dialog (not just OS notification)
Definition: ui_interface.h:65
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:177
std::string str() const
Definition: streams.h:212
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:58
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:207
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
Definition: walletview.cpp:236
void setWalletModel(WalletModel *walletModel)
Set the wallet model.
Definition: walletview.cpp:128
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: walletview.cpp:345
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
Definition: walletview.cpp:215
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:391
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:118
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
void gotoReceiveCoinsPage()
Switch to receive coins page.
Definition: walletview.cpp:211
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
Definition: walletview.cpp:223
QWidget * transactionsPage
Definition: walletview.h:65
void usedSendingAddresses()
Show used sending addresses.
Definition: walletview.cpp:410
ReceiveCoinsDialog * receiveCoinsPage
Definition: walletview.h:66
void encryptWallet()
Encrypt the wallet.
Definition: walletview.cpp:357
TransactionView * transactionView
Definition: walletview.h:71
WalletView(const PlatformStyle *platformStyle, WalletModel *walletModel, QWidget *parent)
Definition: walletview.cpp:43
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
Definition: walletview.cpp:426
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:368
ClientModel * clientModel
Definition: walletview.h:61
void gotoLoadPSBT()
Load Partially Signed Bitcoin Transaction.
Definition: walletview.cpp:249
void requestedSyncWarningInfo()
User has requested more information about the out of sync state.
Definition: walletview.cpp:449
AddressBookPage * usedSendingAddressesPage
Definition: walletview.h:68
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
Definition: walletview.cpp:397
WalletModel * walletModel
Definition: walletview.h:62
void gotoOverviewPage()
Switch to overview (home) page.
Definition: walletview.cpp:203
void usedReceivingAddresses()
Show used receiving addresses.
Definition: walletview.cpp:418
void transactionClicked()
WalletModel * getWalletModel()
Definition: walletview.h:48
void updateEncryptionStatus()
Re-emit encryption status signal.
Definition: walletview.cpp:353
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:169
void showOutOfSyncWarning(bool fShow)
Definition: walletview.cpp:349
void encryptionStatusChanged()
Encryption status of wallet changed.
virtual node::NodeContext * context()
Get and set internal node context.
Definition: node.h:262
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:119
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:251
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:953
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:337
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:294
void bringToFront(QWidget *w)
Definition: guiutil.cpp:390
void setClipboard(const QString &str)
Definition: guiutil.cpp:776
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:152
Span< const std::byte > MakeByteSpan(V &&v) noexcept
Definition: span.h:301
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