Bitcoin ABC  0.26.3
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>
14 #include <qt/askpassphrasedialog.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>
20 #include <qt/receivecoinsdialog.h>
21 #include <qt/sendcoinsdialog.h>
24 #include <qt/transactionview.h>
25 #include <qt/walletmodel.h>
26 #include <util/strencodings.h>
27 
28 #include <QAction>
29 #include <QActionGroup>
30 #include <QFileDialog>
31 #include <QHBoxLayout>
32 #include <QProgressDialog>
33 #include <QPushButton>
34 #include <QVBoxLayout>
35 
36 using node::AnalyzePSBT;
38 using node::PSBTAnalysis;
39 
40 WalletView::WalletView(const PlatformStyle *_platformStyle,
41  WalletModel *_walletModel, QWidget *parent)
42  : QStackedWidget(parent), clientModel(nullptr), walletModel(_walletModel),
43  platformStyle(_platformStyle) {
44  // Create tabs
46 
47  transactionsPage = new QWidget(this);
48  QVBoxLayout *vbox = new QVBoxLayout();
49  QHBoxLayout *hbox_buttons = new QHBoxLayout();
51  vbox->addWidget(transactionView);
52  QPushButton *exportButton = new QPushButton(tr("&Export"), this);
53  exportButton->setToolTip(
54  tr("Export the data in the current tab to a file"));
56  exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
57  }
58  hbox_buttons->addStretch();
59  hbox_buttons->addWidget(exportButton);
60  vbox->addLayout(hbox_buttons);
61  transactionsPage->setLayout(vbox);
62 
65 
72 
73  addWidget(overviewPage);
74  addWidget(transactionsPage);
75  addWidget(receiveCoinsPage);
76  addWidget(sendCoinsPage);
77 
80  // Clicking on a transaction on the overview pre-selects the transaction on
81  // the transaction history page
83  static_cast<void (TransactionView::*)(const QModelIndex &)>(
85 
88 
91  // Highlight transaction after send
93  static_cast<void (TransactionView::*)(const uint256 &)>(
95 
96  // Clicking on "Export" allows to export the transaction list
97  connect(exportButton, &QPushButton::clicked, transactionView,
99 
100  // Pass through messages from sendCoinsPage
101  connect(sendCoinsPage, &SendCoinsDialog::message, this,
103  // Pass through messages from transactionView
106  connect(this, &WalletView::setPrivacy, overviewPage,
108 
109  // Set the model properly.
111 }
112 
114 
116  this->clientModel = _clientModel;
117 
118  overviewPage->setClientModel(_clientModel);
119  sendCoinsPage->setClientModel(_clientModel);
120  if (walletModel) {
121  walletModel->setClientModel(_clientModel);
122  }
123 }
124 
126  this->walletModel = _walletModel;
127 
128  // Put transaction list in tabs
129  transactionView->setModel(_walletModel);
130  overviewPage->setWalletModel(_walletModel);
131  receiveCoinsPage->setModel(_walletModel);
132  sendCoinsPage->setModel(_walletModel);
134  _walletModel ? _walletModel->getAddressTableModel() : nullptr);
136  _walletModel ? _walletModel->getAddressTableModel() : nullptr);
137 
138  if (_walletModel) {
139  // Receive and pass through messages from wallet model
140  connect(_walletModel, &WalletModel::message, this,
142 
143  // Handle changes in encryption status
144  connect(_walletModel, &WalletModel::encryptionStatusChanged, this,
147 
148  // update HD status
149  Q_EMIT hdEnabledStatusChanged();
150 
151  // Balloon pop-up for new transaction
152  connect(_walletModel->getTransactionTableModel(),
153  &TransactionTableModel::rowsInserted, this,
155 
156  // Ask for passphrase if needed
157  connect(_walletModel, &WalletModel::requireUnlock, this,
159 
160  // Show progress dialog
161  connect(_walletModel, &WalletModel::showProgress, this,
163  }
164 }
165 
166 void WalletView::processNewTransaction(const QModelIndex &parent, int start,
167  int end) {
168  // Prevent balloon-spam when initial block download is in progress
169  if (!walletModel || !clientModel ||
171  return;
172  }
173 
175  if (!ttm || ttm->processingQueuedTransactions()) {
176  return;
177  }
178 
179  QString date = ttm->index(start, TransactionTableModel::Date, parent)
180  .data()
181  .toString();
182  qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
183  .data(Qt::EditRole)
184  .toULongLong();
185  QString type = ttm->index(start, TransactionTableModel::Type, parent)
186  .data()
187  .toString();
188  QModelIndex index = ttm->index(start, 0, parent);
189  QString address =
190  ttm->data(index, TransactionTableModel::AddressRole).toString();
191  QString label = GUIUtil::HtmlEscape(
192  ttm->data(index, TransactionTableModel::LabelRole).toString());
193 
194  Q_EMIT incomingTransaction(
196  int64_t(amount) * SATOSHI, type, address, label,
198 }
199 
201  setCurrentWidget(overviewPage);
202 }
203 
205  setCurrentWidget(transactionsPage);
206 }
207 
209  setCurrentWidget(receiveCoinsPage);
210 }
211 
212 void WalletView::gotoSendCoinsPage(QString addr) {
213  setCurrentWidget(sendCoinsPage);
214 
215  if (!addr.isEmpty()) {
216  sendCoinsPage->setAddress(addr);
217  }
218 }
219 
220 void WalletView::gotoSignMessageTab(QString addr) {
221  // calls show() in showTab_SM()
222  SignVerifyMessageDialog *signVerifyMessageDialog =
224  signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
225  signVerifyMessageDialog->setModel(walletModel);
226  signVerifyMessageDialog->showTab_SM(true);
227 
228  if (!addr.isEmpty()) {
229  signVerifyMessageDialog->setAddress_SM(addr);
230  }
231 }
232 
234  // calls show() in showTab_VM()
235  SignVerifyMessageDialog *signVerifyMessageDialog =
237  signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
238  signVerifyMessageDialog->setModel(walletModel);
239  signVerifyMessageDialog->showTab_VM(true);
240 
241  if (!addr.isEmpty()) {
242  signVerifyMessageDialog->setAddress_VM(addr);
243  }
244 }
245 
247  QString filename = GUIUtil::getOpenFileName(
248  this, tr("Load Transaction Data"), QString(),
249  tr("Partially Signed Transaction (*.psbt)"), nullptr);
250  if (filename.isEmpty()) {
251  return;
252  }
253  if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) ==
255  Q_EMIT message(tr("Error"),
256  tr("PSBT file must be smaller than 100 MiB"),
258  return;
259  }
260  fsbridge::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
261  std::string dataStr(std::istreambuf_iterator<char>{in}, {});
262 
263  std::string error;
265  if (!DecodeRawPSBT(psbtx, dataStr, error)) {
266  Q_EMIT message(tr("Error"),
267  tr("Unable to decode PSBT file") + "\n" +
268  QString::fromStdString(error),
270  return;
271  }
272 
274  bool complete = false;
275  PSBTAnalysis analysis = AnalyzePSBT(psbtx);
276  QMessageBox msgBox;
277  msgBox.setText("PSBT");
278  switch (analysis.next) {
279  case PSBTRole::CREATOR:
280  case PSBTRole::UPDATER:
281  msgBox.setInformativeText(
282  "PSBT is incomplete. Copy to clipboard for manual inspection?");
283  break;
284  case PSBTRole::SIGNER:
285  msgBox.setInformativeText(
286  "Transaction needs more signatures. Copy to clipboard?");
287  break;
288  case PSBTRole::FINALIZER:
289  case PSBTRole::EXTRACTOR:
290  complete = FinalizeAndExtractPSBT(psbtx, mtx);
291  if (complete) {
292  msgBox.setInformativeText(
293  tr("Would you like to send this transaction?"));
294  } else {
295  // The analyzer missed something, e.g. if there are
296  // final_scriptSig but with invalid signatures.
297  msgBox.setInformativeText(
298  tr("There was an unexpected problem processing the PSBT. "
299  "Copy to clipboard for manual inspection?"));
300  }
301  }
302 
303  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
304  switch (msgBox.exec()) {
305  case QMessageBox::Yes: {
306  if (complete) {
307  std::string err_string;
309 
311  *clientModel->node().context(), GetConfig(), tx, err_string,
312  DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true,
313  /* wait_callback */ false);
314  if (result == TransactionError::OK) {
315  Q_EMIT message(tr("Success"),
316  tr("Broadcasted transaction successfully."),
319  } else {
320  Q_EMIT message(tr("Error"),
321  QString::fromStdString(err_string),
323  }
324  } else {
325  // Serialize the PSBT
327  ssTx << psbtx;
328  GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
329  Q_EMIT message(tr("PSBT copied"), "Copied to clipboard",
331  return;
332  }
333  }
334  case QMessageBox::Cancel:
335  break;
336  default:
337  assert(false);
338  }
339 }
340 
342  return sendCoinsPage->handlePaymentRequest(recipient);
343 }
344 
347 }
348 
350  Q_EMIT encryptionStatusChanged();
351 }
352 
354  if (!walletModel) {
355  return;
356  }
358  dlg.setModel(walletModel);
359  dlg.exec();
360 
362 }
363 
365  QString filename =
366  GUIUtil::getSaveFileName(this, tr("Backup Wallet"), QString(),
367  tr("Wallet Data (*.dat)"), nullptr);
368 
369  if (filename.isEmpty()) {
370  return;
371  }
372 
373  if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
374  Q_EMIT message(
375  tr("Backup Failed"),
376  tr("There was an error trying to save the wallet data to %1.")
377  .arg(filename),
379  } else {
380  Q_EMIT message(
381  tr("Backup Successful"),
382  tr("The wallet data was successfully saved to %1.").arg(filename),
384  }
385 }
386 
389  dlg.setModel(walletModel);
390  dlg.exec();
391 }
392 
394  if (!walletModel) {
395  return;
396  }
397 
398  // Unlock wallet when requested by wallet model
401  dlg.setModel(walletModel);
402  dlg.exec();
403  }
404 }
405 
407  if (!walletModel) {
408  return;
409  }
410 
412 }
413 
415  if (!walletModel) {
416  return;
417  }
418 
420 }
421 
422 void WalletView::showProgress(const QString &title, int nProgress) {
423  if (nProgress == 0) {
424  progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100);
426  progressDialog->setWindowModality(Qt::ApplicationModal);
427  progressDialog->setMinimumDuration(0);
428  progressDialog->setAutoClose(false);
429  progressDialog->setValue(0);
430  } else if (nProgress == 100) {
431  if (progressDialog) {
432  progressDialog->close();
433  progressDialog->deleteLater();
434  progressDialog = nullptr;
435  }
436  } else if (progressDialog) {
437  if (progressDialog->wasCanceled()) {
439  } else {
440  progressDialog->setValue(nProgress);
441  }
442  }
443 }
444 
446  Q_EMIT outOfSyncWarningClicked();
447 }
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:197
std::string str() const
Definition: streams.h:271
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:280
Model for Bitcoin network client.
Definition: clientmodel.h:36
interfaces::Node & node() const
Definition: clientmodel.h:51
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()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
EncryptionStatus getEncryptionStatus() const
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:204
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
Definition: walletview.cpp:233
void setWalletModel(WalletModel *walletModel)
Set the wallet model.
Definition: walletview.cpp:125
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: walletview.cpp:341
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
Definition: walletview.cpp:212
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:387
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:115
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
void gotoReceiveCoinsPage()
Switch to receive coins page.
Definition: walletview.cpp:208
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
Definition: walletview.cpp:220
QWidget * transactionsPage
Definition: walletview.h:65
void usedSendingAddresses()
Show used sending addresses.
Definition: walletview.cpp:406
ReceiveCoinsDialog * receiveCoinsPage
Definition: walletview.h:66
void encryptWallet()
Encrypt the wallet.
Definition: walletview.cpp:353
TransactionView * transactionView
Definition: walletview.h:71
WalletView(const PlatformStyle *platformStyle, WalletModel *walletModel, QWidget *parent)
Definition: walletview.cpp:40
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
Definition: walletview.cpp:422
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:364
ClientModel * clientModel
Definition: walletview.h:61
void gotoLoadPSBT()
Load Partially Signed Bitcoin Transaction.
Definition: walletview.cpp:246
void requestedSyncWarningInfo()
User has requested more information about the out of sync state.
Definition: walletview.cpp:445
AddressBookPage * usedSendingAddressesPage
Definition: walletview.h:68
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
Definition: walletview.cpp:393
WalletModel * walletModel
Definition: walletview.h:62
void gotoOverviewPage()
Switch to overview (home) page.
Definition: walletview.cpp:200
void usedReceivingAddresses()
Show used receiving addresses.
Definition: walletview.cpp:414
void transactionClicked()
void updateEncryptionStatus()
Re-emit encryption status signal.
Definition: walletview.cpp:349
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:166
void showOutOfSyncWarning(bool fShow)
Definition: walletview.cpp:345
void encryptionStatusChanged()
Encryption status of wallet changed.
WalletModel * getWalletModel()
Definition: walletview.h:48
virtual node::NodeContext * context()
Get and set internal node context.
Definition: node.h:243
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:127
const Config & GetConfig()
Definition: config.cpp:34
TransactionError
Definition: error.h:22
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:243
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:946
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:329
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:286
void bringToFront(QWidget *w)
Definition: guiutil.cpp:382
void setClipboard(const QString &str)
Definition: guiutil.cpp:769
fs::ifstream ifstream
Definition: fs.h:246
TransactionError BroadcastTransaction(NodeContext &node, const Config &config, 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
PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
Provides helpful miscellaneous information about where a PSBT is in the signing workflow.
Definition: psbt.cpp:16
static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE
Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
Definition: transaction.h:32
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:322
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:321
bool DecodeRawPSBT(PartiallySignedTransaction &psbt, const std::string &tx_data, std::string &error)
Decode a raw (binary blob) PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:306
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:246
const std::streamsize MAX_FILE_SIZE_PSBT
Definition: psbt.h:41
@ SER_NETWORK
Definition: serialize.h:166
std::string EncodeBase64(Span< const uint8_t > input)
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::streampos GetFileSize(const char *path, std::streamsize max)
Get the size of a file by scanning it.
Definition: system.cpp:148
bool error(const char *fmt, const Args &...args)
Definition: system.h:45
assert(!tx.IsCoinBase())
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11