Bitcoin Core  21.99.0
P2P Digital Currency
receivecoinsdialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2020 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 <wallet/wallet.h>
6 
8 #include <qt/forms/ui_receivecoinsdialog.h>
9 
10 #include <qt/addresstablemodel.h>
11 #include <qt/guiutil.h>
12 #include <qt/optionsmodel.h>
13 #include <qt/platformstyle.h>
16 #include <qt/walletmodel.h>
17 
18 #include <QAction>
19 #include <QCursor>
20 #include <QMessageBox>
21 #include <QScrollBar>
22 #include <QSettings>
23 #include <QTextDocument>
24 
25 ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
26  QDialog(parent, GUIUtil::dialog_flags),
27  ui(new Ui::ReceiveCoinsDialog),
28  model(nullptr),
29  platformStyle(_platformStyle)
30 {
31  ui->setupUi(this);
32 
33  if (!_platformStyle->getImagesOnButtons()) {
34  ui->clearButton->setIcon(QIcon());
35  ui->receiveButton->setIcon(QIcon());
36  ui->showRequestButton->setIcon(QIcon());
37  ui->removeRequestButton->setIcon(QIcon());
38  } else {
39  ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
40  ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/receiving_addresses"));
41  ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit"));
42  ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
43  }
44 
45  // context menu actions
46  QAction *copyURIAction = new QAction(tr("Copy URI"), this);
47  QAction* copyAddressAction = new QAction(tr("Copy address"), this);
48  copyLabelAction = new QAction(tr("Copy label"), this);
49  copyMessageAction = new QAction(tr("Copy message"), this);
50  copyAmountAction = new QAction(tr("Copy amount"), this);
51 
52  // context menu
53  contextMenu = new QMenu(this);
54  contextMenu->addAction(copyURIAction);
55  contextMenu->addAction(copyAddressAction);
56  contextMenu->addAction(copyLabelAction);
57  contextMenu->addAction(copyMessageAction);
58  contextMenu->addAction(copyAmountAction);
59 
60  // context menu signals
61  connect(ui->recentRequestsView, &QWidget::customContextMenuRequested, this, &ReceiveCoinsDialog::showMenu);
62  connect(copyURIAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyURI);
63  connect(copyAddressAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyAddress);
64  connect(copyLabelAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyLabel);
65  connect(copyMessageAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyMessage);
66  connect(copyAmountAction, &QAction::triggered, this, &ReceiveCoinsDialog::copyAmount);
67 
68  connect(ui->clearButton, &QPushButton::clicked, this, &ReceiveCoinsDialog::clear);
69 
70  QTableView* tableView = ui->recentRequestsView;
71  tableView->verticalHeader()->hide();
72  tableView->setAlternatingRowColors(true);
73  tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
74  tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
75 
76  QSettings settings;
77  if (!tableView->horizontalHeader()->restoreState(settings.value("RecentRequestsViewHeaderState").toByteArray())) {
78  tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
79  tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);
81  tableView->horizontalHeader()->setMinimumSectionSize(MINIMUM_COLUMN_WIDTH);
82  tableView->horizontalHeader()->setStretchLastSection(true);
83  }
84 }
85 
87 {
88  this->model = _model;
89 
90  if(_model && _model->getOptionsModel())
91  {
92  _model->getRecentRequestsTableModel()->sort(RecentRequestsTableModel::Date, Qt::DescendingOrder);
95 
96  QTableView* tableView = ui->recentRequestsView;
97  tableView->setModel(_model->getRecentRequestsTableModel());
98  tableView->sortByColumn(RecentRequestsTableModel::Date, Qt::DescendingOrder);
99 
100  connect(tableView->selectionModel(),
101  &QItemSelectionModel::selectionChanged, this,
103 
105  ui->useBech32->setCheckState(Qt::Checked);
106  } else {
107  ui->useBech32->setCheckState(Qt::Unchecked);
108  }
109 
110  // Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
111  ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
112 
113  // Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
114  connect(model, &WalletModel::canGetAddressesChanged, [this] {
115  ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
116  });
117  }
118 }
119 
121 {
122  QSettings settings;
123  settings.setValue("RecentRequestsViewHeaderState", ui->recentRequestsView->horizontalHeader()->saveState());
124  delete ui;
125 }
126 
128 {
129  ui->reqAmount->clear();
130  ui->reqLabel->setText("");
131  ui->reqMessage->setText("");
133 }
134 
136 {
137  clear();
138 }
139 
141 {
142  clear();
143 }
144 
146 {
147  if(model && model->getOptionsModel())
148  {
149  ui->reqAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
150  }
151 }
152 
154 {
156  return;
157 
158  QString address;
159  QString label = ui->reqLabel->text();
160  /* Generate new receiving address */
161  OutputType address_type;
162  if (ui->useBech32->isChecked()) {
163  address_type = OutputType::BECH32;
164  } else {
165  address_type = model->wallet().getDefaultAddressType();
166  if (address_type == OutputType::BECH32) {
167  address_type = OutputType::P2SH_SEGWIT;
168  }
169  }
170  address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
171 
173  {
174  case AddressTableModel::EditStatus::OK: {
175  // Success
176  SendCoinsRecipient info(address, label,
177  ui->reqAmount->value(), ui->reqMessage->text());
178  ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
179  dialog->setAttribute(Qt::WA_DeleteOnClose);
180  dialog->setModel(model);
181  dialog->setInfo(info);
182  dialog->show();
183 
184  /* Store request for later reference */
186  break;
187  }
188  case AddressTableModel::EditStatus::WALLET_UNLOCK_FAILURE:
189  QMessageBox::critical(this, windowTitle(),
190  tr("Could not unlock wallet."),
191  QMessageBox::Ok, QMessageBox::Ok);
192  break;
193  case AddressTableModel::EditStatus::KEY_GENERATION_FAILURE:
194  QMessageBox::critical(this, windowTitle(),
195  tr("Could not generate new %1 address").arg(QString::fromStdString(FormatOutputType(address_type))),
196  QMessageBox::Ok, QMessageBox::Ok);
197  break;
198  // These aren't valid return values for our action
199  case AddressTableModel::EditStatus::INVALID_ADDRESS:
200  case AddressTableModel::EditStatus::DUPLICATE_ADDRESS:
201  case AddressTableModel::EditStatus::NO_CHANGES:
202  assert(false);
203  }
204  clear();
205 }
206 
208 {
210  ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
211  dialog->setModel(model);
212  dialog->setInfo(submodel->entry(index.row()).recipient);
213  dialog->setAttribute(Qt::WA_DeleteOnClose);
214  dialog->show();
215 }
216 
217 void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
218 {
219  // Enable Show/Remove buttons only if anything is selected.
220  bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty();
221  ui->showRequestButton->setEnabled(enable);
222  ui->removeRequestButton->setEnabled(enable);
223 }
224 
226 {
227  if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
228  return;
229  QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
230 
231  for (const QModelIndex& index : selection) {
233  }
234 }
235 
237 {
238  if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
239  return;
240  QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
241  if(selection.empty())
242  return;
243  // correct for selection mode ContiguousSelection
244  QModelIndex firstIndex = selection.at(0);
245  model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
246 }
247 
249 {
250  if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
251  return QModelIndex();
252  QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
253  if(selection.empty())
254  return QModelIndex();
255  // correct for selection mode ContiguousSelection
256  QModelIndex firstIndex = selection.at(0);
257  return firstIndex;
258 }
259 
260 // copy column of selected row to clipboard
262 {
263  QModelIndex firstIndex = selectedRow();
264  if (!firstIndex.isValid()) {
265  return;
266  }
267  GUIUtil::setClipboard(model->getRecentRequestsTableModel()->index(firstIndex.row(), column).data(Qt::EditRole).toString());
268 }
269 
270 // context menu
271 void ReceiveCoinsDialog::showMenu(const QPoint &point)
272 {
273  const QModelIndex sel = selectedRow();
274  if (!sel.isValid()) {
275  return;
276  }
277 
278  // disable context menu actions when appropriate
280  const RecentRequestEntry& req = submodel->entry(sel.row());
281  copyLabelAction->setDisabled(req.recipient.label.isEmpty());
282  copyMessageAction->setDisabled(req.recipient.message.isEmpty());
283  copyAmountAction->setDisabled(req.recipient.amount == 0);
284 
285  contextMenu->exec(QCursor::pos());
286 }
287 
288 // context menu action: copy URI
290 {
291  QModelIndex sel = selectedRow();
292  if (!sel.isValid()) {
293  return;
294  }
295 
296  const RecentRequestsTableModel * const submodel = model->getRecentRequestsTableModel();
297  const QString uri = GUIUtil::formatBitcoinURI(submodel->entry(sel.row()).recipient);
299 }
300 
301 // context menu action: copy address
303 {
304  const QModelIndex sel = selectedRow();
305  if (!sel.isValid()) {
306  return;
307  }
308 
310  const QString address = submodel->entry(sel.row()).recipient.address;
311  GUIUtil::setClipboard(address);
312 }
313 
314 // context menu action: copy label
316 {
318 }
319 
320 // context menu action: copy message
322 {
324 }
325 
326 // context menu action: copy amount
328 {
330 }
ReceiveCoinsDialog::AMOUNT_MINIMUM_COLUMN_WIDTH
@ AMOUNT_MINIMUM_COLUMN_WIDTH
Definition: receivecoinsdialog.h:38
SendCoinsRecipient::amount
CAmount amount
Definition: sendcoinsrecipient.h:33
WalletModel::getOptionsModel
OptionsModel * getOptionsModel()
Definition: walletmodel.cpp:281
RecentRequestEntry::recipient
SendCoinsRecipient recipient
Definition: recentrequeststablemodel.h:25
ReceiveRequestDialog::setModel
void setModel(WalletModel *model)
Definition: receiverequestdialog.cpp:35
OutputType
OutputType
Definition: outputtype.h:17
ReceiveCoinsDialog
Dialog for requesting payment of bitcoins.
Definition: receivecoinsdialog.h:30
wallet.h
ReceiveCoinsDialog::setModel
void setModel(WalletModel *model)
Definition: receivecoinsdialog.cpp:86
WalletModel
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:51
RecentRequestsTableModel::Amount
@ Amount
Definition: recentrequeststablemodel.h:62
ReceiveCoinsDialog::ReceiveCoinsDialog
ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
Definition: receivecoinsdialog.cpp:25
ReceiveCoinsDialog::copyAmount
void copyAmount()
Definition: receivecoinsdialog.cpp:327
ReceiveCoinsDialog::MINIMUM_COLUMN_WIDTH
@ MINIMUM_COLUMN_WIDTH
Definition: receivecoinsdialog.h:39
FormatOutputType
const std::string & FormatOutputType(OutputType type)
Definition: outputtype.cpp:37
PlatformStyle::SingleColorIcon
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Definition: platformstyle.cpp:102
RecentRequestsTableModel::entry
const RecentRequestEntry & entry(int row) const
Definition: recentrequeststablemodel.h:79
walletmodel.h
ReceiveCoinsDialog::LABEL_COLUMN_WIDTH
@ LABEL_COLUMN_WIDTH
Definition: receivecoinsdialog.h:37
WalletModel::getAddressTableModel
AddressTableModel * getAddressTableModel()
Definition: walletmodel.cpp:286
ReceiveCoinsDialog::ui
Ui::ReceiveCoinsDialog * ui
Definition: receivecoinsdialog.h:53
SendCoinsRecipient::label
QString label
Definition: sendcoinsrecipient.h:32
GUIUtil
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:58
ReceiveCoinsDialog::on_receiveButton_clicked
void on_receiveButton_clicked()
Definition: receivecoinsdialog.cpp:153
AddressTableModel::Receive
static const QString Receive
Specifies receive address.
Definition: addresstablemodel.h:51
OptionsModel::displayUnitChanged
void displayUnitChanged(int unit)
WalletModel::canGetAddressesChanged
void canGetAddressesChanged()
GUIUtil::formatBitcoinURI
QString formatBitcoinURI(const SendCoinsRecipient &info)
Definition: guiutil.cpp:185
ReceiveCoinsDialog::on_removeRequestButton_clicked
void on_removeRequestButton_clicked()
Definition: receivecoinsdialog.cpp:236
ReceiveCoinsDialog::model
WalletModel * model
Definition: receivecoinsdialog.h:54
GUIUtil::dialog_flags
constexpr auto dialog_flags
Definition: guiutil.h:51
ReceiveCoinsDialog::updateDisplayUnit
void updateDisplayUnit()
Definition: receivecoinsdialog.cpp:145
GUIUtil::setClipboard
void setClipboard(const QString &str)
Definition: guiutil.cpp:629
RecentRequestsTableModel::removeRows
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
Definition: recentrequeststablemodel.cpp:137
ReceiveRequestDialog::setInfo
void setInfo(const SendCoinsRecipient &info)
Definition: receiverequestdialog.cpp:46
SendCoinsRecipient
Definition: sendcoinsrecipient.h:19
ReceiveCoinsDialog::copyMessage
void copyMessage()
Definition: receivecoinsdialog.cpp:321
WalletModel::wallet
interfaces::Wallet & wallet() const
Definition: walletmodel.h:146
ReceiveCoinsDialog::copyColumnToClipboard
void copyColumnToClipboard(int column)
Definition: receivecoinsdialog.cpp:261
AddressTableModel::addRow
QString addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type)
Definition: addresstablemodel.cpp:343
ReceiveCoinsDialog::contextMenu
QMenu * contextMenu
Definition: receivecoinsdialog.h:55
PlatformStyle::getImagesOnButtons
bool getImagesOnButtons() const
Definition: platformstyle.h:21
ReceiveCoinsDialog::selectedRow
QModelIndex selectedRow()
Definition: receivecoinsdialog.cpp:248
RecentRequestsTableModel
Model for list of recently generated payment requests / bitcoin: URIs.
Definition: recentrequeststablemodel.h:50
recentrequeststablemodel.h
guiutil.h
interfaces::Wallet::canGetAddresses
virtual bool canGetAddresses()=0
ReceiveCoinsDialog::on_recentRequestsView_doubleClicked
void on_recentRequestsView_doubleClicked(const QModelIndex &index)
Definition: receivecoinsdialog.cpp:207
ReceiveCoinsDialog::recentRequestsView_selectionChanged
void recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Definition: receivecoinsdialog.cpp:217
WalletModel::getRecentRequestsTableModel
RecentRequestsTableModel * getRecentRequestsTableModel()
Definition: walletmodel.cpp:296
ReceiveCoinsDialog::copyLabel
void copyLabel()
Definition: receivecoinsdialog.cpp:315
RecentRequestsTableModel::addNewRequest
void addNewRequest(const SendCoinsRecipient &recipient)
Definition: recentrequeststablemodel.cpp:165
ReceiveRequestDialog
Definition: receiverequestdialog.h:18
ReceiveCoinsDialog::~ReceiveCoinsDialog
~ReceiveCoinsDialog()
Definition: receivecoinsdialog.cpp:120
RecentRequestsTableModel::index
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: recentrequeststablemodel.cpp:130
OutputType::P2SH_SEGWIT
@ P2SH_SEGWIT
AddressTableModel::getEditStatus
EditStatus getEditStatus() const
Definition: addresstablemodel.h:81
RecentRequestsTableModel::Date
@ Date
Definition: recentrequeststablemodel.h:59
platformstyle.h
OutputType::BECH32
@ BECH32
ReceiveCoinsDialog::showMenu
void showMenu(const QPoint &point)
Definition: receivecoinsdialog.cpp:271
ReceiveCoinsDialog::copyMessageAction
QAction * copyMessageAction
Definition: receivecoinsdialog.h:57
ReceiveCoinsDialog::DATE_COLUMN_WIDTH
@ DATE_COLUMN_WIDTH
Definition: receivecoinsdialog.h:36
ReceiveCoinsDialog::accept
void accept() override
Definition: receivecoinsdialog.cpp:140
interfaces::Wallet::getDefaultAddressType
virtual OutputType getDefaultAddressType()=0
Ui
Definition: addressbookpage.h:14
receivecoinsdialog.h
OptionsModel::getDisplayUnit
int getDisplayUnit() const
Definition: optionsmodel.h:86
SendCoinsRecipient::address
QString address
Definition: sendcoinsrecipient.h:31
ReceiveCoinsDialog::reject
void reject() override
Definition: receivecoinsdialog.cpp:135
RecentRequestsTableModel::Label
@ Label
Definition: recentrequeststablemodel.h:60
RecentRequestsTableModel::sort
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Definition: recentrequeststablemodel.cpp:207
ReceiveCoinsDialog::copyLabelAction
QAction * copyLabelAction
Definition: receivecoinsdialog.h:56
RecentRequestsTableModel::Message
@ Message
Definition: recentrequeststablemodel.h:61
ReceiveCoinsDialog::clear
void clear()
Definition: receivecoinsdialog.cpp:127
optionsmodel.h
ReceiveCoinsDialog::on_showRequestButton_clicked
void on_showRequestButton_clicked()
Definition: receivecoinsdialog.cpp:225
ReceiveCoinsDialog::copyURI
void copyURI()
Definition: receivecoinsdialog.cpp:289
PlatformStyle
Definition: platformstyle.h:13
ReceiveCoinsDialog::copyAmountAction
QAction * copyAmountAction
Definition: receivecoinsdialog.h:58
receiverequestdialog.h
assert
assert(std::addressof(::ChainstateActive().CoinsTip())==std::addressof(coins_cache))
addresstablemodel.h
ReceiveCoinsDialog::copyAddress
void copyAddress()
Definition: receivecoinsdialog.cpp:302
RecentRequestEntry
Definition: recentrequeststablemodel.h:16
SendCoinsRecipient::message
QString message
Definition: sendcoinsrecipient.h:35