Bitcoin ABC 0.32.12
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/types.h>
12#include <node/ui_interface.h>
13#include <policy/policy.h>
14#include <qt/addressbookpage.h>
16#include <qt/clientmodel.h>
17#include <qt/guiutil.h>
18#include <qt/optionsmodel.h>
19#include <qt/overviewpage.h>
20#include <qt/platformstyle.h>
22#include <qt/sendcoinsdialog.h>
25#include <qt/transactionview.h>
26#include <qt/walletmodel.h>
27#include <util/fs_helpers.h>
28#include <util/strencodings.h>
29
30#include <QAction>
31#include <QFileDialog>
32#include <QHBoxLayout>
33#include <QProgressDialog>
34#include <QPushButton>
35#include <QVBoxLayout>
36
37#include <fstream>
38
43
45 WalletModel *_walletModel, QWidget *parent)
46 : QStackedWidget(parent), clientModel(nullptr), walletModel(_walletModel),
47 platformStyle(_platformStyle) {
48 // Create tabs
50
51 transactionsPage = new QWidget(this);
52 QVBoxLayout *vbox = new QVBoxLayout();
53 QHBoxLayout *hbox_buttons = new QHBoxLayout();
55 vbox->addWidget(transactionView);
56 QPushButton *exportButton = new QPushButton(tr("&Export"), this);
57 exportButton->setToolTip(
58 tr("Export the data in the current tab to a file"));
60 exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
61 }
62 hbox_buttons->addStretch();
63 hbox_buttons->addWidget(exportButton);
64 vbox->addLayout(hbox_buttons);
65 transactionsPage->setLayout(vbox);
66
69
76
77 addWidget(overviewPage);
78 addWidget(transactionsPage);
79 addWidget(receiveCoinsPage);
80 addWidget(sendCoinsPage);
81
84 // Clicking on a transaction on the overview pre-selects the transaction on
85 // the transaction history page
87 static_cast<void (TransactionView::*)(const QModelIndex &)>(
89
92
95 // Highlight transaction after send
97 static_cast<void (TransactionView::*)(const uint256 &)>(
99
100 // Clicking on "Export" allows to export the transaction list
101 connect(exportButton, &QPushButton::clicked, transactionView,
103
104 // Pass through messages from sendCoinsPage
107 // Pass through messages from transactionView
110 connect(this, &WalletView::setPrivacy, overviewPage,
112
113 // Set the model properly.
115}
116
117WalletView::~WalletView() = default;
118
120 this->clientModel = _clientModel;
121
122 overviewPage->setClientModel(_clientModel);
123 sendCoinsPage->setClientModel(_clientModel);
124 if (walletModel) {
125 walletModel->setClientModel(_clientModel);
126 }
127}
128
130 this->walletModel = _walletModel;
131
132 // Put transaction list in tabs
133 transactionView->setModel(_walletModel);
134 overviewPage->setWalletModel(_walletModel);
135 receiveCoinsPage->setModel(_walletModel);
136 sendCoinsPage->setModel(_walletModel);
138 _walletModel ? _walletModel->getAddressTableModel() : nullptr);
140 _walletModel ? _walletModel->getAddressTableModel() : nullptr);
141
142 if (_walletModel) {
143 // Receive and pass through messages from wallet model
144 connect(_walletModel, &WalletModel::message, this,
146
147 // Handle changes in encryption status
148 connect(_walletModel, &WalletModel::encryptionStatusChanged, this,
151
152 // update HD status
153 Q_EMIT hdEnabledStatusChanged();
154
155 // Balloon pop-up for new transaction
156 connect(_walletModel->getTransactionTableModel(),
157 &TransactionTableModel::rowsInserted, this,
159
160 // Ask for passphrase if needed
161 connect(_walletModel, &WalletModel::requireUnlock, this,
163
164 // Show progress dialog
165 connect(_walletModel, &WalletModel::showProgress, this,
167 }
168}
169
170void WalletView::processNewTransaction(const QModelIndex &parent, int start,
171 int end) {
172 // Prevent balloon-spam when initial block download is in progress
173 if (!walletModel || !clientModel ||
175 return;
176 }
177
179 if (!ttm || ttm->processingQueuedTransactions()) {
180 return;
181 }
182
183 QString date = ttm->index(start, TransactionTableModel::Date, parent)
184 .data()
185 .toString();
186 qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
187 .data(Qt::EditRole)
188 .toULongLong();
189 QString type = ttm->index(start, TransactionTableModel::Type, parent)
190 .data()
191 .toString();
192 QModelIndex index = ttm->index(start, 0, parent);
193 QString address =
194 ttm->data(index, TransactionTableModel::AddressRole).toString();
195 QString label = GUIUtil::HtmlEscape(
196 ttm->data(index, TransactionTableModel::LabelRole).toString());
197
198 Q_EMIT incomingTransaction(
200 int64_t(amount) * SATOSHI, type, address, label,
202}
203
205 setCurrentWidget(overviewPage);
206}
207
209 setCurrentWidget(transactionsPage);
210}
211
213 setCurrentWidget(receiveCoinsPage);
214}
215
217 setCurrentWidget(sendCoinsPage);
218
219 if (!addr.isEmpty()) {
221 }
222}
223
225 // calls show() in showTab_SM()
226 SignVerifyMessageDialog *signVerifyMessageDialog =
228 signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
229 signVerifyMessageDialog->setModel(walletModel);
230 signVerifyMessageDialog->showTab_SM(true);
231
232 if (!addr.isEmpty()) {
233 signVerifyMessageDialog->setAddress_SM(addr);
234 }
235}
236
238 // calls show() in showTab_VM()
239 SignVerifyMessageDialog *signVerifyMessageDialog =
241 signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
242 signVerifyMessageDialog->setModel(walletModel);
243 signVerifyMessageDialog->showTab_VM(true);
244
245 if (!addr.isEmpty()) {
246 signVerifyMessageDialog->setAddress_VM(addr);
247 }
248}
249
251 QString filename = GUIUtil::getOpenFileName(
252 this, tr("Load Transaction Data"), QString(),
253 tr("Partially Signed Transaction (*.psbt)"), nullptr);
254 if (filename.isEmpty()) {
255 return;
256 }
257 if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) ==
259 Q_EMIT message(tr("Error"),
260 tr("PSBT file must be smaller than 100 MiB"),
262 return;
263 }
264 std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
265 std::vector<uint8_t> data;
266 data.assign(std::istream_iterator<uint8_t>{in}, {});
267
268 std::string error;
270 if (!DecodeRawPSBT(psbtx, MakeByteSpan(data), error)) {
271 Q_EMIT message(tr("Error"),
272 tr("Unable to decode PSBT file") + "\n" +
273 QString::fromStdString(error),
275 return;
276 }
277
279 bool complete = false;
280 PSBTAnalysis analysis = AnalyzePSBT(psbtx);
281 QMessageBox msgBox;
282 msgBox.setText("PSBT");
283 switch (analysis.next) {
286 msgBox.setInformativeText(
287 "PSBT is incomplete. Copy to clipboard for manual inspection?");
288 break;
289 case PSBTRole::SIGNER:
290 msgBox.setInformativeText(
291 "Transaction needs more signatures. Copy to clipboard?");
292 break;
295 complete = FinalizeAndExtractPSBT(psbtx, mtx);
296 if (complete) {
297 msgBox.setInformativeText(
298 tr("Would you like to send this transaction?"));
299 } else {
300 // The analyzer missed something, e.g. if there are
301 // final_scriptSig but with invalid signatures.
302 msgBox.setInformativeText(
303 tr("There was an unexpected problem processing the PSBT. "
304 "Copy to clipboard for manual inspection?"));
305 }
306 }
307
308 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
309 switch (msgBox.exec()) {
310 case QMessageBox::Yes: {
311 if (complete) {
312 std::string err_string;
314
316 *clientModel->node().context(), tx, err_string,
317 DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true,
318 /* wait_callback */ false);
319 if (result == TransactionError::OK) {
320 Q_EMIT message(tr("Success"),
321 tr("Broadcasted transaction successfully."),
324 } else {
325 Q_EMIT message(tr("Error"),
326 QString::fromStdString(err_string),
328 }
329 } else {
330 // Serialize the PSBT
331 DataStream ssTx{};
332 ssTx << psbtx;
333 GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
334 Q_EMIT message(tr("PSBT copied"), "Copied to clipboard",
336 return;
337 }
338 }
339 case QMessageBox::Cancel:
340 break;
341 default:
342 assert(false);
343 }
344}
345
347 return sendCoinsPage->handlePaymentRequest(recipient);
348}
349
352}
353
356}
357
359 if (!walletModel) {
360 return;
361 }
363 dlg->setModel(walletModel);
364 connect(dlg, &QDialog::finished, this,
367}
368
370 QString filename =
371 GUIUtil::getSaveFileName(this, tr("Backup Wallet"), QString(),
372 tr("Wallet Data (*.dat)"), nullptr);
373
374 if (filename.isEmpty()) {
375 return;
376 }
377
378 if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
379 Q_EMIT message(
380 tr("Backup Failed"),
381 tr("There was an error trying to save the wallet data to %1.")
382 .arg(filename),
384 } else {
385 Q_EMIT message(
386 tr("Backup Successful"),
387 tr("The wallet data was successfully saved to %1.").arg(filename),
389 }
390}
391
394 dlg->setModel(walletModel);
396}
397
399 if (!walletModel) {
400 return;
401 }
402
403 // Unlock wallet when requested by wallet model
407 // A modal dialog must be synchronous here as expected
408 // in the WalletModel::requestUnlock() function.
409 dlg.exec();
410 }
411}
412
414 if (!walletModel) {
415 return;
416 }
417
419}
420
422 if (!walletModel) {
423 return;
424 }
425
427}
428
429void WalletView::showProgress(const QString &title, int nProgress) {
430 if (nProgress == 0) {
431 progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100);
433 progressDialog->setWindowModality(Qt::ApplicationModal);
434 progressDialog->setMinimumDuration(0);
435 progressDialog->setAutoClose(false);
436 progressDialog->setValue(0);
437 } else if (nProgress == 100) {
438 if (progressDialog) {
439 progressDialog->close();
440 progressDialog->deleteLater();
441 progressDialog = nullptr;
442 }
443 } else if (progressDialog) {
444 if (progressDialog->wasCanceled()) {
446 } else {
447 progressDialog->setValue(nProgress);
448 }
449 }
450}
451
454}
static constexpr Amount SATOSHI
Definition: amount.h:148
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
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:118
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:208
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
Definition: walletview.cpp:237
void setWalletModel(WalletModel *walletModel)
Set the wallet model.
Definition: walletview.cpp:129
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: walletview.cpp:346
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
Definition: walletview.cpp:216
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:392
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:119
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
void gotoReceiveCoinsPage()
Switch to receive coins page.
Definition: walletview.cpp:212
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
Definition: walletview.cpp:224
QWidget * transactionsPage
Definition: walletview.h:65
void usedSendingAddresses()
Show used sending addresses.
Definition: walletview.cpp:413
ReceiveCoinsDialog * receiveCoinsPage
Definition: walletview.h:66
void encryptWallet()
Encrypt the wallet.
Definition: walletview.cpp:358
TransactionView * transactionView
Definition: walletview.h:71
WalletView(const PlatformStyle *platformStyle, WalletModel *walletModel, QWidget *parent)
Definition: walletview.cpp:44
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
Definition: walletview.cpp:429
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:369
ClientModel * clientModel
Definition: walletview.h:61
void gotoLoadPSBT()
Load Partially Signed Bitcoin Transaction.
Definition: walletview.cpp:250
void requestedSyncWarningInfo()
User has requested more information about the out of sync state.
Definition: walletview.cpp:452
AddressBookPage * usedSendingAddressesPage
Definition: walletview.h:68
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
Definition: walletview.cpp:398
WalletModel * walletModel
Definition: walletview.h:62
void gotoOverviewPage()
Switch to overview (home) page.
Definition: walletview.cpp:204
void usedReceivingAddresses()
Show used receiving addresses.
Definition: walletview.cpp:421
void transactionClicked()
WalletModel * getWalletModel()
Definition: walletview.h:48
void updateEncryptionStatus()
Re-emit encryption status signal.
Definition: walletview.cpp:354
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:170
void showOutOfSyncWarning(bool fShow)
Definition: walletview.cpp:350
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
std::streampos GetFileSize(const char *path, std::streamsize max)
Get the size of a file by scanning it.
Definition: fs_helpers.cpp:105
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:38
TransactionError
Definition: types.h:17
static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE
Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
Definition: transaction.h:33
is a home for public enum and struct type definitions that are used by internally by node code,...
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:304
const std::streamsize MAX_FILE_SIZE_PSBT
Definition: psbt.h:41
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())