Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
receivecoinsdialog.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2022 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 platformStyle(_platformStyle)
29{
30 ui->setupUi(this);
31
32 if (!_platformStyle->getImagesOnButtons()) {
33 ui->clearButton->setIcon(QIcon());
34 ui->receiveButton->setIcon(QIcon());
35 ui->showRequestButton->setIcon(QIcon());
36 ui->removeRequestButton->setIcon(QIcon());
37 } else {
38 ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
39 ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/receiving_addresses"));
40 ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/eye"));
41 ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
42 }
43
44 // context menu
45 contextMenu = new QMenu(this);
46 contextMenu->addAction(tr("Copy &URI"), this, &ReceiveCoinsDialog::copyURI);
47 contextMenu->addAction(tr("&Copy address"), this, &ReceiveCoinsDialog::copyAddress);
48 copyLabelAction = contextMenu->addAction(tr("Copy &label"), this, &ReceiveCoinsDialog::copyLabel);
49 copyMessageAction = contextMenu->addAction(tr("Copy &message"), this, &ReceiveCoinsDialog::copyMessage);
50 copyAmountAction = contextMenu->addAction(tr("Copy &amount"), this, &ReceiveCoinsDialog::copyAmount);
51 connect(ui->recentRequestsView, &QWidget::customContextMenuRequested, this, &ReceiveCoinsDialog::showMenu);
52
53 connect(ui->clearButton, &QPushButton::clicked, this, &ReceiveCoinsDialog::clear);
54
55 QTableView* tableView = ui->recentRequestsView;
56 tableView->verticalHeader()->hide();
57 tableView->setAlternatingRowColors(true);
58 tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
59 tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
60
61 QSettings settings;
62 if (!tableView->horizontalHeader()->restoreState(settings.value("RecentRequestsViewHeaderState").toByteArray())) {
63 tableView->setColumnWidth(RecentRequestsTableModel::Date, DATE_COLUMN_WIDTH);
64 tableView->setColumnWidth(RecentRequestsTableModel::Label, LABEL_COLUMN_WIDTH);
66 tableView->horizontalHeader()->setMinimumSectionSize(MINIMUM_COLUMN_WIDTH);
67 tableView->horizontalHeader()->setStretchLastSection(true);
68 }
69}
70
72{
73 this->model = _model;
74
75 if(_model && _model->getOptionsModel())
76 {
80
81 QTableView* tableView = ui->recentRequestsView;
82 tableView->setModel(_model->getRecentRequestsTableModel());
83 tableView->sortByColumn(RecentRequestsTableModel::Date, Qt::DescendingOrder);
84
85 connect(tableView->selectionModel(),
86 &QItemSelectionModel::selectionChanged, this,
88
89 // Populate address type dropdown and select default
90 auto add_address_type = [&](OutputType type, const QString& text, const QString& tooltip) {
91 const auto index = ui->addressType->count();
92 ui->addressType->addItem(text, (int) type);
93 ui->addressType->setItemData(index, tooltip, Qt::ToolTipRole);
94 if (model->wallet().getDefaultAddressType() == type) ui->addressType->setCurrentIndex(index);
95 };
96 add_address_type(OutputType::LEGACY, tr("Base58 (Legacy)"), tr("Not recommended due to higher fees and less protection against typos."));
97 add_address_type(OutputType::P2SH_SEGWIT, tr("Base58 (P2SH-SegWit)"), tr("Generates an address compatible with older wallets."));
98 add_address_type(OutputType::BECH32, tr("Bech32 (SegWit)"), tr("Generates a native segwit address (BIP-173). Some old wallets don't support it."));
99 if (model->wallet().taprootEnabled()) {
100 add_address_type(OutputType::BECH32M, tr("Bech32m (Taproot)"), tr("Bech32m (BIP-350) is an upgrade to Bech32, wallet support is still limited."));
101 }
102
103 // Set the button to be enabled or disabled based on whether the wallet can give out new addresses.
104 ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
105
106 // Enable/disable the receive button if the wallet is now able/unable to give out new addresses.
108 ui->receiveButton->setEnabled(model->wallet().canGetAddresses());
109 });
110 }
111}
112
114{
115 QSettings settings;
116 settings.setValue("RecentRequestsViewHeaderState", ui->recentRequestsView->horizontalHeader()->saveState());
117 delete ui;
118}
119
121{
122 ui->reqAmount->clear();
123 ui->reqLabel->setText("");
124 ui->reqMessage->setText("");
126}
127
129{
130 clear();
131}
132
134{
135 clear();
136}
137
145
147{
149 return;
150
151 QString address;
152 QString label = ui->reqLabel->text();
153 /* Generate new receiving address */
154 const OutputType address_type = (OutputType)ui->addressType->currentData().toInt();
155 address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type);
156
158 {
160 // Success
161 SendCoinsRecipient info(address, label,
162 ui->reqAmount->value(), ui->reqMessage->text());
163 ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
164 dialog->setAttribute(Qt::WA_DeleteOnClose);
165 dialog->setModel(model);
166 dialog->setInfo(info);
167 dialog->show();
168
169 /* Store request for later reference */
171 break;
172 }
174 QMessageBox::critical(this, windowTitle(),
175 tr("Could not unlock wallet."),
176 QMessageBox::Ok, QMessageBox::Ok);
177 break;
179 QMessageBox::critical(this, windowTitle(),
180 tr("Could not generate new %1 address").arg(QString::fromStdString(FormatOutputType(address_type))),
181 QMessageBox::Ok, QMessageBox::Ok);
182 break;
183 // These aren't valid return values for our action
187 assert(false);
188 }
189 clear();
190}
191
193{
195 ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
196 dialog->setModel(model);
197 dialog->setInfo(submodel->entry(index.row()).recipient);
198 dialog->setAttribute(Qt::WA_DeleteOnClose);
199 dialog->show();
200}
201
202void ReceiveCoinsDialog::recentRequestsView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
203{
204 // Enable Show/Remove buttons only if anything is selected.
205 bool enable = !ui->recentRequestsView->selectionModel()->selectedRows().isEmpty();
206 ui->showRequestButton->setEnabled(enable);
207 ui->removeRequestButton->setEnabled(enable);
208}
209
211{
212 if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
213 return;
214 QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
215
216 for (const QModelIndex& index : selection) {
218 }
219}
220
222{
223 if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
224 return;
225 QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
226 if(selection.empty())
227 return;
228 // correct for selection mode ContiguousSelection
229 QModelIndex firstIndex = selection.at(0);
230 model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
231}
232
234{
235 if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
236 return QModelIndex();
237 QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
238 if(selection.empty())
239 return QModelIndex();
240 // correct for selection mode ContiguousSelection
241 QModelIndex firstIndex = selection.at(0);
242 return firstIndex;
243}
244
245// copy column of selected row to clipboard
247{
248 QModelIndex firstIndex = selectedRow();
249 if (!firstIndex.isValid()) {
250 return;
251 }
252 GUIUtil::setClipboard(model->getRecentRequestsTableModel()->index(firstIndex.row(), column).data(Qt::EditRole).toString());
253}
254
255// context menu
256void ReceiveCoinsDialog::showMenu(const QPoint &point)
257{
258 const QModelIndex sel = selectedRow();
259 if (!sel.isValid()) {
260 return;
261 }
262
263 // disable context menu actions when appropriate
265 const RecentRequestEntry& req = submodel->entry(sel.row());
266 copyLabelAction->setDisabled(req.recipient.label.isEmpty());
267 copyMessageAction->setDisabled(req.recipient.message.isEmpty());
268 copyAmountAction->setDisabled(req.recipient.amount == 0);
269
270 contextMenu->exec(QCursor::pos());
271}
272
273// context menu action: copy URI
275{
276 QModelIndex sel = selectedRow();
277 if (!sel.isValid()) {
278 return;
279 }
280
282 const QString uri = GUIUtil::formatBitcoinURI(submodel->entry(sel.row()).recipient);
284}
285
286// context menu action: copy address
288{
289 const QModelIndex sel = selectedRow();
290 if (!sel.isValid()) {
291 return;
292 }
293
295 const QString address = submodel->entry(sel.row()).recipient.address;
296 GUIUtil::setClipboard(address);
297}
298
299// context menu action: copy label
304
305// context menu action: copy message
310
311// context menu action: copy amount
EditStatus getEditStatus() const
@ WALLET_UNLOCK_FAILURE
Wallet could not be unlocked to create new receiving address.
@ NO_CHANGES
No changes were made during edit operation.
@ INVALID_ADDRESS
Unparseable address.
@ KEY_GENERATION_FAILURE
Generating a new public key for a receiving address failed.
@ OK
Everything ok.
@ DUPLICATE_ADDRESS
Address already in address book.
QString addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type)
static const QString Receive
Specifies receive address.
void setDisplayUnit(BitcoinUnit new_unit)
Change unit used to display amount.
void clear()
Make field empty and ready for new input.
void displayUnitChanged(BitcoinUnit unit)
BitcoinUnit getDisplayUnit() const
bool getImagesOnButtons() const
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:48
RecentRequestsTableModel * getRecentRequestsTableModel() const
AddressTableModel * getAddressTableModel() const
interfaces::Wallet & wallet() const
OptionsModel * getOptionsModel() const
void canGetAddressesChanged()
virtual OutputType getDefaultAddressType()=0
virtual bool taprootEnabled()=0
virtual bool canGetAddresses()=0
Utility functions used by the Bitcoin Qt UI.
Definition bitcoingui.h:58
QString formatBitcoinURI(const SendCoinsRecipient &info)
Definition guiutil.cpp:211
void setClipboard(const QString &str)
Definition guiutil.cpp:668
const std::string & FormatOutputType(OutputType type)
OutputType
Definition outputtype.h:17
assert(!tx.IsCoinBase())