Bitcoin Core 22.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
9
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
25ReceiveCoinsDialog::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
46 contextMenu = new QMenu(this);
47 contextMenu->addAction(tr("Copy &URI"), this, &ReceiveCoinsDialog::copyURI);
48 contextMenu->addAction(tr("&Copy address"), this, &ReceiveCoinsDialog::copyAddress);
49 copyLabelAction = contextMenu->addAction(tr("Copy &label"), this, &ReceiveCoinsDialog::copyLabel);
50 copyMessageAction = contextMenu->addAction(tr("Copy &message"), this, &ReceiveCoinsDialog::copyMessage);
51 copyAmountAction = contextMenu->addAction(tr("Copy &amount"), this, &ReceiveCoinsDialog::copyAmount);
52 connect(ui->recentRequestsView, &QWidget::customContextMenuRequested, this, &ReceiveCoinsDialog::showMenu);
53
54 connect(ui->clearButton, &QPushButton::clicked, this, &ReceiveCoinsDialog::clear);
55
56 QTableView* tableView = ui->recentRequestsView;
57 tableView->verticalHeader()->hide();
58 tableView->setAlternatingRowColors(true);
59 tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
60 tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
61
62 QSettings settings;
63 if (!tableView->horizontalHeader()->restoreState(settings.value("RecentRequestsViewHeaderState").toByteArray())) {
64 tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
65 tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);
67 tableView->horizontalHeader()->setMinimumSectionSize(MINIMUM_COLUMN_WIDTH);
68 tableView->horizontalHeader()->setStretchLastSection(true);
69 }
70}
71
73{
74 this->model = _model;
75
76 if(_model && _model->getOptionsModel())
77 {
81
82 QTableView* tableView = ui->recentRequestsView;
83 tableView->setModel(_model->getRecentRequestsTableModel());
84 tableView->sortByColumn(RecentRequestsTableModel::Date, Qt::DescendingOrder);
85
86 connect(tableView->selectionModel(),
87 &QItemSelectionModel::selectionChanged, this,
89
91 ui->useBech32->setCheckState(Qt::Checked);
92 } else {
93 ui->useBech32->setCheckState(Qt::Unchecked);
94 }
95
96 // Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
97 ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
98
99 // Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
101 ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
102 });
103 }
104}
105
107{
108 QSettings settings;
109 settings.setValue("RecentRequestsViewHeaderState", ui->recentRequestsView->horizontalHeader()->saveState());
110 delete ui;
111}
112
114{
115 ui->reqAmount->clear();
116 ui->reqLabel->setText("");
117 ui->reqMessage->setText("");
119}
120
122{
123 clear();
124}
125
127{
128 clear();
129}
130
132{
133 if(model && model->getOptionsModel())
134 {
136 }
137}
138
140{
142 return;
143
144 QString address;
145 QString label = ui->reqLabel->text();
146 /* Generate new receiving address */
147 OutputType address_type;
148 if (ui->useBech32->isChecked()) {
149 address_type = OutputType::BECH32;
150 } else {
151 address_type = model->wallet().getDefaultAddressType();
152 if (address_type == OutputType::BECH32) {
153 address_type = OutputType::P2SH_SEGWIT;
154 }
155 }
156 address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
157
159 {
160 case AddressTableModel::EditStatus::OK: {
161 // Success
162 SendCoinsRecipient info(address, label,
163 ui->reqAmount->value(), ui->reqMessage->text());
164 ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
165 dialog->setAttribute(Qt::WA_DeleteOnClose);
166 dialog->setModel(model);
167 dialog->setInfo(info);
168 dialog->show();
169
170 /* Store request for later reference */
172 break;
173 }
174 case AddressTableModel::EditStatus::WALLET_UNLOCK_FAILURE:
175 QMessageBox::critical(this, windowTitle(),
176 tr("Could not unlock wallet."),
177 QMessageBox::Ok, QMessageBox::Ok);
178 break;
179 case AddressTableModel::EditStatus::KEY_GENERATION_FAILURE:
180 QMessageBox::critical(this, windowTitle(),
181 tr("Could not generate new %1 address").arg(QString::fromStdString(FormatOutputType(address_type))),
182 QMessageBox::Ok, QMessageBox::Ok);
183 break;
184 // These aren't valid return values for our action
185 case AddressTableModel::EditStatus::INVALID_ADDRESS:
186 case AddressTableModel::EditStatus::DUPLICATE_ADDRESS:
187 case AddressTableModel::EditStatus::NO_CHANGES:
188 assert(false);
189 }
190 clear();
191}
192
194{
196 ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
197 dialog->setModel(model);
198 dialog->setInfo(submodel->entry(index.row()).recipient);
199 dialog->setAttribute(Qt::WA_DeleteOnClose);
200 dialog->show();
201}
202
203void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
204{
205 // Enable Show/Remove buttons only if anything is selected.
206 bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty();
207 ui->showRequestButton->setEnabled(enable);
208 ui->removeRequestButton->setEnabled(enable);
209}
210
212{
213 if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
214 return;
215 QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
216
217 for (const QModelIndex& index : selection) {
219 }
220}
221
223{
224 if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
225 return;
226 QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
227 if(selection.empty())
228 return;
229 // correct for selection mode ContiguousSelection
230 QModelIndex firstIndex = selection.at(0);
231 model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
232}
233
235{
236 if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
237 return QModelIndex();
238 QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
239 if(selection.empty())
240 return QModelIndex();
241 // correct for selection mode ContiguousSelection
242 QModelIndex firstIndex = selection.at(0);
243 return firstIndex;
244}
245
246// copy column of selected row to clipboard
248{
249 QModelIndex firstIndex = selectedRow();
250 if (!firstIndex.isValid()) {
251 return;
252 }
253 GUIUtil::setClipboard(model->getRecentRequestsTableModel()->index(firstIndex.row(), column).data(Qt::EditRole).toString());
254}
255
256// context menu
257void ReceiveCoinsDialog::showMenu(const QPoint &point)
258{
259 const QModelIndex sel = selectedRow();
260 if (!sel.isValid()) {
261 return;
262 }
263
264 // disable context menu actions when appropriate
266 const RecentRequestEntry& req = submodel->entry(sel.row());
267 copyLabelAction->setDisabled(req.recipient.label.isEmpty());
268 copyMessageAction->setDisabled(req.recipient.message.isEmpty());
269 copyAmountAction->setDisabled(req.recipient.amount == 0);
270
271 contextMenu->exec(QCursor::pos());
272}
273
274// context menu action: copy URI
276{
277 QModelIndex sel = selectedRow();
278 if (!sel.isValid()) {
279 return;
280 }
281
283 const QString uri = GUIUtil::formatBitcoinURI(submodel->entry(sel.row()).recipient);
285}
286
287// context menu action: copy address
289{
290 const QModelIndex sel = selectedRow();
291 if (!sel.isValid()) {
292 return;
293 }
294
296 const QString address = submodel->entry(sel.row()).recipient.address;
297 GUIUtil::setClipboard(address);
298}
299
300// context menu action: copy label
302{
304}
305
306// context menu action: copy message
308{
310}
311
312// context menu action: copy amount
314{
316}
EditStatus getEditStatus() const
QString addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type)
static const QString Receive
Specifies receive address.
void setDisplayUnit(int unit)
Change unit used to display amount.
void clear()
Make field empty and ready for new input.
int getDisplayUnit() const
Definition: optionsmodel.h:88
void displayUnitChanged(int unit)
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
bool getImagesOnButtons() const
Definition: platformstyle.h:21
Dialog for requesting payment of bitcoins.
Ui::ReceiveCoinsDialog * ui
void on_recentRequestsView_doubleClicked(const QModelIndex &index)
void recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void setModel(WalletModel *model)
void showMenu(const QPoint &point)
ReceiveCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
void copyColumnToClipboard(int column)
void setModel(WalletModel *model)
void setInfo(const SendCoinsRecipient &info)
SendCoinsRecipient recipient
Model for list of recently generated payment requests / bitcoin: URIs.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
const RecentRequestEntry & entry(int row) const
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
void addNewRequest(const SendCoinsRecipient &recipient)
BitcoinAmountField * reqAmount
void setupUi(QDialog *ReceiveCoinsDialog)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:52
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:144
RecentRequestsTableModel * getRecentRequestsTableModel()
void canGetAddressesChanged()
virtual OutputType getDefaultAddressType()=0
virtual bool canGetAddresses()=0
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:59
QString formatBitcoinURI(const SendCoinsRecipient &info)
Definition: guiutil.cpp:195
constexpr auto dialog_flags
Definition: guiutil.h:60
void setClipboard(const QString &str)
Definition: guiutil.cpp:645
const std::string & FormatOutputType(OutputType type)
Definition: outputtype.cpp:38
OutputType
Definition: outputtype.h:18
assert(!tx.IsCoinBase())