5 #if defined(HAVE_CONFIG_H) 6 #include <config/bitcoin-config.h> 10 #include <qt/forms/ui_coincontroldialog.h> 25 #include <QApplication> 28 #include <QDialogButtonBox> 32 #include <QTreeWidget> 38 int column = treeWidget()->sortColumn();
42 return data(column, Qt::UserRole).toLongLong() <
43 other.data(column, Qt::UserRole).toLongLong();
51 platformStyle(_platformStyle) {
55 QAction *copyAddressAction =
new QAction(tr(
"Copy address"),
this);
56 QAction *copyLabelAction =
new QAction(tr(
"Copy label"),
this);
57 QAction *copyAmountAction =
new QAction(tr(
"Copy amount"),
this);
61 lockAction =
new QAction(tr(
"Lock unspent"),
this);
76 connect(
ui->treeWidget, &QWidget::customContextMenuRequested,
this,
78 connect(copyAddressAction, &QAction::triggered,
this,
80 connect(copyLabelAction, &QAction::triggered,
this,
82 connect(copyAmountAction, &QAction::triggered,
this,
92 QAction *clipboardQuantityAction =
new QAction(tr(
"Copy quantity"),
this);
93 QAction *clipboardAmountAction =
new QAction(tr(
"Copy amount"),
this);
94 QAction *clipboardFeeAction =
new QAction(tr(
"Copy fee"),
this);
95 QAction *clipboardAfterFeeAction =
new QAction(tr(
"Copy after fee"),
this);
96 QAction *clipboardBytesAction =
new QAction(tr(
"Copy bytes"),
this);
97 QAction *clipboardLowOutputAction =
new QAction(tr(
"Copy dust"),
this);
98 QAction *clipboardChangeAction =
new QAction(tr(
"Copy change"),
this);
100 connect(clipboardQuantityAction, &QAction::triggered,
this,
102 connect(clipboardAmountAction, &QAction::triggered,
this,
104 connect(clipboardFeeAction, &QAction::triggered,
this,
106 connect(clipboardAfterFeeAction, &QAction::triggered,
this,
108 connect(clipboardBytesAction, &QAction::triggered,
this,
110 connect(clipboardLowOutputAction, &QAction::triggered,
this,
112 connect(clipboardChangeAction, &QAction::triggered,
this,
115 ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
116 ui->labelCoinControlAmount->addAction(clipboardAmountAction);
117 ui->labelCoinControlFee->addAction(clipboardFeeAction);
118 ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
119 ui->labelCoinControlBytes->addAction(clipboardBytesAction);
120 ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
121 ui->labelCoinControlChange->addAction(clipboardChangeAction);
124 connect(
ui->radioTreeMode, &QRadioButton::toggled,
this,
126 connect(
ui->radioListMode, &QRadioButton::toggled,
this,
130 connect(
ui->treeWidget, &QTreeWidget::itemChanged,
this,
134 ui->treeWidget->header()->setSectionsClickable(
true);
135 connect(
ui->treeWidget->header(), &QHeaderView::sectionClicked,
this,
139 connect(
ui->buttonBox, &QDialogButtonBox::clicked,
this,
143 connect(
ui->pushButtonSelectAll, &QPushButton::clicked,
this,
158 if (settings.contains(
"nCoinControlMode") &&
159 !settings.value(
"nCoinControlMode").toBool()) {
160 ui->radioTreeMode->click();
162 if (settings.contains(
"nCoinControlSortColumn") &&
163 settings.contains(
"nCoinControlSortOrder")) {
164 sortView(settings.value(
"nCoinControlSortColumn").toInt(),
165 (
static_cast<Qt::SortOrder
>(
166 settings.value(
"nCoinControlSortOrder").toInt())));
172 settings.setValue(
"nCoinControlMode",
ui->radioListMode->isChecked());
173 settings.setValue(
"nCoinControlSortColumn",
sortColumn);
174 settings.setValue(
"nCoinControlSortOrder", (
int)
sortOrder);
180 this->
model = _model;
191 if (
ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
193 done(QDialog::Accepted);
199 Qt::CheckState state = Qt::Checked;
200 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++) {
203 state = Qt::Unchecked;
207 ui->treeWidget->setEnabled(
false);
208 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++) {
215 ui->treeWidget->setEnabled(
true);
216 if (state == Qt::Unchecked) {
225 QTreeWidgetItem *item =
ui->treeWidget->itemAt(point);
264 if (
ui->radioTreeMode->isChecked() &&
275 if (
ui->radioTreeMode->isChecked() &&
321 ui->labelCoinControlAmount->text().indexOf(
" ")));
327 ui->labelCoinControlFee->text()
328 .left(
ui->labelCoinControlFee->text().indexOf(
" "))
335 ui->labelCoinControlAfterFee->text()
336 .left(
ui->labelCoinControlAfterFee->text().indexOf(
" "))
343 ui->labelCoinControlBytes->text().replace(
ASYMP_UTF8,
""));
354 ui->labelCoinControlChange->text()
355 .left(
ui->labelCoinControlChange->text().indexOf(
" "))
363 ui->treeWidget->sortItems(column, order);
375 ((
sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder
376 : Qt::AscendingOrder);
383 : Qt::DescendingOrder);
392 if (checked &&
model) {
399 if (checked &&
model) {
414 }
else if (item->isDisabled()) {
422 if (
ui->treeWidget->isEnabled()) {
434 Qt::PartiallyChecked) {
442 std::vector<COutPoint> vOutpts;
444 if (vOutpts.size() > 0) {
445 ui->labelLocked->setText(tr(
"(%1 locked)").arg(vOutpts.size()));
446 ui->labelLocked->setVisible(
true);
448 ui->labelLocked->setVisible(
false);
462 nPayAmount += amount;
466 CTxOut txout(amount,
CScript() << std::vector<uint8_t>(24, 0));
467 txDummy.
vout.push_back(txout);
476 unsigned int nBytes = 0;
477 unsigned int nBytesInputs = 0;
478 unsigned int nQuantity = 0;
480 std::vector<COutPoint> vCoinControl;
485 if (out.depth_in_main_chain < 0) {
491 const COutPoint &output = vCoinControl[i++];
501 nAmount += out.txout.nValue;
507 PKHash *pkhash = boost::get<PKHash>(&address);
509 CKeyID(*pkhash), pubkey)) {
524 nBytes = nBytesInputs +
525 ((CoinControlDialog::payAmounts.size() > 0
526 ? CoinControlDialog::payAmounts.size() + 1
544 nChange = nAmount - nPayAmount;
553 CTxOut txout(nChange,
CScript() << std::vector<uint8_t>(24, 0));
571 nAfterFee = std::max(nAmount - nPayFee,
Amount::zero());
580 QLabel *l1 = dialog->findChild<QLabel *>(
"labelCoinControlQuantity");
581 QLabel *l2 = dialog->findChild<QLabel *>(
"labelCoinControlAmount");
582 QLabel *l3 = dialog->findChild<QLabel *>(
"labelCoinControlFee");
583 QLabel *l4 = dialog->findChild<QLabel *>(
"labelCoinControlAfterFee");
584 QLabel *l5 = dialog->findChild<QLabel *>(
"labelCoinControlBytes");
585 QLabel *l7 = dialog->findChild<QLabel *>(
"labelCoinControlLowOutput");
586 QLabel *l8 = dialog->findChild<QLabel *>(
"labelCoinControlChange");
589 dialog->findChild<QLabel *>(
"labelCoinControlLowOutputText")
591 dialog->findChild<QLabel *>(
"labelCoinControlLowOutput")
593 dialog->findChild<QLabel *>(
"labelCoinControlChangeText")
595 dialog->findChild<QLabel *>(
"labelCoinControlChange")
600 l1->setText(QString::number(nQuantity));
608 l5->setText(((nBytes > 0) ?
ASYMP_UTF8 :
"") + QString::number(nBytes));
610 l7->setText(fDust ? tr(
"yes") : tr(
"no"));
623 l7->setStyleSheet((fDust) ?
"color:red;" :
"");
626 QString toolTipDust =
627 tr(
"This label turns red if any recipient receives an amount smaller " 628 "than the current dust threshold.");
631 double dFeeVary = (nBytes != 0) ?
double(nPayFee /
SATOSHI) / nBytes : 0;
634 tr(
"Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
636 l3->setToolTip(toolTip4);
637 l4->setToolTip(toolTip4);
638 l7->setToolTip(toolTipDust);
639 l8->setToolTip(toolTip4);
640 dialog->findChild<QLabel *>(
"labelCoinControlFeeText")
641 ->setToolTip(l3->toolTip());
642 dialog->findChild<QLabel *>(
"labelCoinControlAfterFeeText")
643 ->setToolTip(l4->toolTip());
644 dialog->findChild<QLabel *>(
"labelCoinControlBytesText")
645 ->setToolTip(l5->toolTip());
646 dialog->findChild<QLabel *>(
"labelCoinControlLowOutputText")
647 ->setToolTip(l7->toolTip());
648 dialog->findChild<QLabel *>(
"labelCoinControlChangeText")
649 ->setToolTip(l8->toolTip());
652 QLabel *label = dialog->findChild<QLabel *>(
"labelCoinControlInsuffFunds");
660 return &coin_control;
674 bool treeMode =
ui->radioTreeMode->isChecked();
676 ui->treeWidget->clear();
679 ui->treeWidget->setEnabled(
false);
680 ui->treeWidget->setAlternatingRowColors(!treeMode);
681 QFlags<Qt::ItemFlag> flgCheckbox =
682 Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
683 QFlags<Qt::ItemFlag> flgTristate =
684 Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable |
693 QString sWalletAddress = QString::fromStdString(
695 QString sWalletLabel =
697 if (sWalletLabel.isEmpty()) {
698 sWalletLabel = tr(
"(no label)");
703 ui->treeWidget->addTopLevelItem(itemWalletAddress);
705 itemWalletAddress->setFlags(flgTristate);
717 for (
const auto &outpair : coins.second) {
718 const COutPoint &output = std::get<0>(outpair);
720 nSum += out.txout.nValue;
729 itemOutput->setFlags(flgCheckbox);
734 QString sAddress =
"";
736 sAddress = QString::fromStdString(
741 if (!treeMode || (!(sAddress == sWalletAddress))) {
747 if (!(sAddress == sWalletAddress)) {
749 itemOutput->setToolTip(
COLUMN_LABEL, tr(
"change from %1 (%2)")
751 .arg(sWalletAddress));
753 }
else if (!treeMode) {
756 if (sLabel.isEmpty()) {
757 sLabel = tr(
"(no label)");
769 QVariant(qlonglong(out.txout.nValue /
SATOSHI)));
774 QVariant((qlonglong)out.time));
778 QString::number(out.depth_in_main_chain));
780 QVariant((qlonglong)out.depth_in_main_chain));
794 itemOutput->setDisabled(
true);
809 "(" + QString::number(nChildren) +
")");
810 itemWalletAddress->setText(
813 QVariant(qlonglong(nSum /
SATOSHI)));
819 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++) {
821 Qt::PartiallyChecked) {
822 ui->treeWidget->topLevelItem(i)->setExpanded(
true);
829 ui->treeWidget->setEnabled(
true);
const PlatformStyle * platformStyle
void viewItemChanged(QTreeWidgetItem *, int)
static QString formatWithUnit(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
virtual CoinsList listCoins()=0
interfaces::Wallet & wallet() const
static constexpr Amount zero()
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
void buttonSelectAllClicked()
void clipboardLowOutput()
static QList< Amount > payAmounts
void headerSectionClicked(int)
void copyTransactionHash()
virtual bool getPubKey(const CScript &script, const CKeyID &address, CPubKey &pub_key)=0
Get public key.
void ListSelected(std::vector< COutPoint > &vOutpoints) const
static COutPoint buildOutPoint(const QTreeWidgetItem *item)
QString dateTimeStr(const QDateTime &date)
const TxId & GetTxId() const
static constexpr Amount SATOSHI
virtual void lockCoin(const COutPoint &output)=0
Lock coin.
std::vector< CTxOut > vout
AddressTableModel * getAddressTableModel()
void UnSelect(const COutPoint &output)
virtual CFeeRate getDustRelayFee()=0
Get dust relay fee.
int getDisplayUnit() const
QAction * copyTransactionHashAction
const CChainParams & getChainParams() const
virtual void unlockCoin(const COutPoint &output)=0
Unlock coin.
Ui::CoinControlDialog * ui
void setClipboard(const QString &str)
virtual Amount getMinimumFee(unsigned int tx_bytes, const CCoinControl &coin_control)=0
Get minimum fee.
void Select(const COutPoint &output)
An encapsulated public key.
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
static void updateLabels(WalletModel *, QDialog *)
friend class CCoinControlWidgetItem
An output of a transaction.
An outpoint - a combination of a transaction hash and an index n into its vout.
interfaces::Node & node() const
static QString format(int unit, const Amount amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
virtual std::vector< WalletTxOut > getCoins(const std::vector< COutPoint > &outputs)=0
Return wallet transaction output information.
bool operator<(const CNetAddr &a, const CNetAddr &b)
void setModel(WalletModel *model)
static bool fSubtractFeeFromAmount
QTreeWidgetItem * contextMenuItem
virtual void listLockedCoins(std::vector< COutPoint > &outputs)=0
List locked coins.
Serialized script, used inside transaction inputs and outputs.
Interface to Bitcoin wallet from Qt view code.
A TxId is the identifier of a transaction.
bool IsSelected(const COutPoint &output) const
static QString removeSpaces(QString text)
A mutable version of CTransaction.
A reference to a CKey: the Hash160 of its serialized public key.
std::string GetHex() const
void sortView(int, Qt::SortOrder)
virtual bool isLockedCoin(const COutPoint &output)=0
Return whether coin is locked.
std::string EncodeCashAddr(const CTxDestination &dst, const CChainParams ¶ms)
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
void buttonBoxClicked(QAbstractButton *)
static constexpr Amount MIN_CHANGE
target minimum change amount
void showMenu(const QPoint &)
Wallet transaction output.
void SetHex(const char *psz)
boost::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
OptionsModel * getOptionsModel()
static CCoinControl * coinControl()
bool IsCompressed() const
Check whether this is a compressed public key.