6 #include "ui_coincontroldialog.h"
19 #include "validation.h"
22 #include <boost/assign/list_of.hpp>
24 #include <QApplication>
27 #include <QDialogButtonBox>
32 #include <QTreeWidget>
33 #include <QTreeWidgetItem>
40 int column = treeWidget()->sortColumn();
42 return data(column, Qt::UserRole).toLongLong() < other.data(column, Qt::UserRole).toLongLong();
50 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);
59 lockAction =
new QAction(tr(
"Lock unspent"),
this);
73 connect(
ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(
showMenu(QPoint)));
74 connect(copyAddressAction, SIGNAL(triggered()),
this, SLOT(
copyAddress()));
75 connect(copyLabelAction, SIGNAL(triggered()),
this, SLOT(
copyLabel()));
76 connect(copyAmountAction, SIGNAL(triggered()),
this, SLOT(
copyAmount()));
82 QAction *clipboardQuantityAction =
new QAction(tr(
"Copy quantity"),
this);
83 QAction *clipboardAmountAction =
new QAction(tr(
"Copy amount"),
this);
84 QAction *clipboardFeeAction =
new QAction(tr(
"Copy fee"),
this);
85 QAction *clipboardAfterFeeAction =
new QAction(tr(
"Copy after fee"),
this);
86 QAction *clipboardBytesAction =
new QAction(tr(
"Copy bytes"),
this);
87 QAction *clipboardLowOutputAction =
new QAction(tr(
"Copy dust"),
this);
88 QAction *clipboardChangeAction =
new QAction(tr(
"Copy change"),
this);
90 connect(clipboardQuantityAction, SIGNAL(triggered()),
this, SLOT(
clipboardQuantity()));
91 connect(clipboardAmountAction, SIGNAL(triggered()),
this, SLOT(
clipboardAmount()));
92 connect(clipboardFeeAction, SIGNAL(triggered()),
this, SLOT(
clipboardFee()));
93 connect(clipboardAfterFeeAction, SIGNAL(triggered()),
this, SLOT(
clipboardAfterFee()));
94 connect(clipboardBytesAction, SIGNAL(triggered()),
this, SLOT(
clipboardBytes()));
95 connect(clipboardLowOutputAction, SIGNAL(triggered()),
this, SLOT(
clipboardLowOutput()));
96 connect(clipboardChangeAction, SIGNAL(triggered()),
this, SLOT(
clipboardChange()));
98 ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
99 ui->labelCoinControlAmount->addAction(clipboardAmountAction);
100 ui->labelCoinControlFee->addAction(clipboardFeeAction);
101 ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
102 ui->labelCoinControlBytes->addAction(clipboardBytesAction);
103 ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
104 ui->labelCoinControlChange->addAction(clipboardChangeAction);
107 connect(
ui->radioTreeMode, SIGNAL(toggled(
bool)),
this, SLOT(
radioTreeMode(
bool)));
108 connect(
ui->radioListMode, SIGNAL(toggled(
bool)),
this, SLOT(
radioListMode(
bool)));
111 connect(
ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,
int)),
this, SLOT(
viewItemChanged(QTreeWidgetItem*,
int)));
114 #if QT_VERSION < 0x050000
115 ui->treeWidget->header()->setClickable(
true);
117 ui->treeWidget->header()->setSectionsClickable(
true);
122 connect(
ui->buttonBox, SIGNAL(clicked( QAbstractButton*)),
this, SLOT(
buttonBoxClicked(QAbstractButton*)));
145 if (settings.contains(
"nCoinControlMode") && !settings.value(
"nCoinControlMode").toBool())
146 ui->radioTreeMode->click();
147 if (settings.contains(
"nCoinControlSortColumn") && settings.contains(
"nCoinControlSortOrder"))
148 sortView(settings.value(
"nCoinControlSortColumn").toInt(), ((Qt::SortOrder)settings.value(
"nCoinControlSortOrder").toInt()));
154 settings.setValue(
"nCoinControlMode",
ui->radioListMode->isChecked());
155 settings.setValue(
"nCoinControlSortColumn",
sortColumn);
156 settings.setValue(
"nCoinControlSortOrder", (
int)
sortOrder);
163 this->
model = _model;
176 if (
ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
177 done(QDialog::Accepted);
183 Qt::CheckState state = Qt::Checked;
184 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
186 if (
ui->treeWidget->topLevelItem(i)->checkState(
COLUMN_CHECKBOX) != Qt::Unchecked)
188 state = Qt::Unchecked;
192 ui->treeWidget->setEnabled(
false);
193 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
196 ui->treeWidget->setEnabled(
true);
197 if (state == Qt::Unchecked)
205 QTreeWidgetItem *item =
ui->treeWidget->itemAt(point);
337 ui->treeWidget->sortItems(column, order);
351 sortOrder = ((
sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder);
365 if (checked &&
model)
372 if (checked &&
model)
385 else if (item->isDisabled())
391 if (
ui->treeWidget->isEnabled())
397 #if QT_VERSION >= 0x050000
409 std::vector<COutPoint> vOutpts;
411 if (vOutpts.size() > 0)
413 ui->labelLocked->setText(tr(
"(%1 locked)").arg(vOutpts.size()));
414 ui->labelLocked->setVisible(
true);
416 else ui->labelLocked->setVisible(
false);
430 nPayAmount += amount;
434 CTxOut txout(amount, (
CScript)std::vector<unsigned char>(24, 0));
435 txDummy.
vout.push_back(txout);
445 unsigned int nBytes = 0;
446 unsigned int nBytesInputs = 0;
447 double dPriority = 0;
448 double dPriorityInputs = 0;
449 unsigned int nQuantity = 0;
450 int nQuantityUncompressed = 0;
451 bool fAllowFree =
false;
452 bool fWitness =
false;
454 std::vector<COutPoint> vCoinControl;
455 std::vector<COutput> vOutputs;
459 BOOST_FOREACH(
const COutput& out, vOutputs) {
474 nAmount += out.
tx->
tx->vout[out.
i].nValue;
477 dPriorityInputs += (double)out.
tx->
tx->vout[out.
i].nValue * (out.
nDepth+1);
481 int witnessversion = 0;
482 std::vector<unsigned char> witnessprogram;
483 if (out.
tx->
tx->vout[out.
i].scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram))
485 nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
491 CKeyID *keyid = boost::get<CKeyID>(&address);
496 nQuantityUncompressed++;
501 else nBytesInputs += 148;
520 if (nAmount - nPayAmount == 0)
531 dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29));
533 fAllowFree = (dPriority >= dPriorityNeeded);
536 if (fAllowFree && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
541 nChange = nAmount - nPayAmount;
546 if (nChange > 0 && nChange < MIN_CHANGE)
548 CTxOut txout(nChange, (
CScript)std::vector<unsigned char>(24, 0));
566 nAfterFee = std::max<CAmount>(nAmount - nPayFee, 0);
574 QLabel *l1 = dialog->findChild<QLabel *>(
"labelCoinControlQuantity");
575 QLabel *l2 = dialog->findChild<QLabel *>(
"labelCoinControlAmount");
576 QLabel *l3 = dialog->findChild<QLabel *>(
"labelCoinControlFee");
577 QLabel *l4 = dialog->findChild<QLabel *>(
"labelCoinControlAfterFee");
578 QLabel *l5 = dialog->findChild<QLabel *>(
"labelCoinControlBytes");
579 QLabel *l7 = dialog->findChild<QLabel *>(
"labelCoinControlLowOutput");
580 QLabel *l8 = dialog->findChild<QLabel *>(
"labelCoinControlChange");
583 dialog->findChild<QLabel *>(
"labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0);
584 dialog->findChild<QLabel *>(
"labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0);
585 dialog->findChild<QLabel *>(
"labelCoinControlChangeText") ->setEnabled(nPayAmount > 0);
586 dialog->findChild<QLabel *>(
"labelCoinControlChange") ->setEnabled(nPayAmount > 0);
589 l1->setText(QString::number(nQuantity));
593 l5->setText(((nBytes > 0) ?
ASYMP_UTF8 :
"") + QString::number(nBytes));
594 l7->setText(fDust ? tr(
"yes") : tr(
"no"));
605 l7->setStyleSheet((fDust) ?
"color:red;" :
"");
608 QString toolTipDust = tr(
"This label turns red if any recipient receives an amount smaller than the current dust threshold.");
617 QString toolTip4 = tr(
"Can vary +/- %1 koinu(s) per input.").arg(dFeeVary);
619 l3->setToolTip(toolTip4);
620 l4->setToolTip(toolTip4);
621 l7->setToolTip(toolTipDust);
622 l8->setToolTip(toolTip4);
623 dialog->findChild<QLabel *>(
"labelCoinControlFeeText") ->setToolTip(l3->toolTip());
624 dialog->findChild<QLabel *>(
"labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip());
625 dialog->findChild<QLabel *>(
"labelCoinControlBytesText") ->setToolTip(l5->toolTip());
626 dialog->findChild<QLabel *>(
"labelCoinControlLowOutputText")->setToolTip(l7->toolTip());
627 dialog->findChild<QLabel *>(
"labelCoinControlChangeText") ->setToolTip(l8->toolTip());
630 QLabel *label = dialog->findChild<QLabel *>(
"labelCoinControlInsuffFunds");
632 label->setVisible(nChange < 0);
640 bool treeMode =
ui->radioTreeMode->isChecked();
642 ui->treeWidget->clear();
643 ui->treeWidget->setEnabled(
false);
644 ui->treeWidget->setAlternatingRowColors(!treeMode);
645 QFlags<Qt::ItemFlag> flgCheckbox = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
646 QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
650 std::map<QString, std::vector<COutput> > mapCoins;
653 BOOST_FOREACH(
const PAIRTYPE(QString, std::vector<COutput>)& coins, mapCoins) {
656 QString sWalletAddress = coins.first;
658 if (sWalletLabel.isEmpty())
659 sWalletLabel = tr(
"(no label)");
664 ui->treeWidget->addTopLevelItem(itemWalletAddress);
666 itemWalletAddress->setFlags(flgTristate);
678 BOOST_FOREACH(
const COutput& out, coins.second) {
679 nSum += out.
tx->
tx->vout[out.
i].nValue;
685 itemOutput->setFlags(flgCheckbox);
690 QString sAddress =
"";
693 sAddress = QString::fromStdString(
CBitcoinAddress(outputAddress).ToString());
696 if (!treeMode || (!(sAddress == sWalletAddress)))
701 if (!(sAddress == sWalletAddress))
704 itemOutput->setToolTip(
COLUMN_LABEL, tr(
"change from %1 (%2)").arg(sWalletLabel).arg(sWalletAddress));
710 if (sLabel.isEmpty())
711 sLabel = tr(
"(no label)");
717 itemOutput->setData(
COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.
tx->
tx->vout[out.
i].nValue));
739 itemOutput->setDisabled(
true);
751 itemWalletAddress->setText(
COLUMN_CHECKBOX,
"(" + QString::number(nChildren) +
")");
753 itemWalletAddress->setData(
COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)nSum));
760 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
761 if (
ui->treeWidget->topLevelItem(i)->checkState(
COLUMN_CHECKBOX) == Qt::PartiallyChecked)
762 ui->treeWidget->topLevelItem(i)->setExpanded(
true);
767 ui->treeWidget->setEnabled(
true);
int64_t CAmount
Amount in satoshis (Can be negative)
QString labelForAddress(const QString &address) const
static QString removeSpaces(QString text)
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string.
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
base58-encoded Bitcoin addresses.
bool IsSelected(const COutPoint &output) const
void Select(const COutPoint &output)
void UnSelect(const COutPoint &output)
void ListSelected(std::vector< COutPoint > &vOutpoints) const
CAmount nMinimumTotalFee
Minimum absolute fee (not per kilobyte)
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
A reference to a CKey: the Hash160 of its serialized public key.
const uint256 & GetHash() const
An outpoint - a combination of a transaction hash and an index n into its vout.
An encapsulated public key.
bool IsCompressed() const
Check whether this is a compressed public key.
Serialized script, used inside transaction inputs and outputs.
CFeeRate estimateSmartFee(int nBlocks, int *answerFoundAtBlocks=NULL) const
Estimate fee rate needed to get into the next nBlocks If no answer can be given at nBlocks,...
double estimateSmartPriority(int nBlocks, int *answerFoundAtBlocks=NULL) const
Estimate priority needed to get into the next nBlocks If no answer can be given at nBlocks,...
An output of a transaction.
CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const
bool IsDust(const CFeeRate &minRelayTxFee) const
void headerSectionClicked(int)
QTreeWidgetItem * contextMenuItem
friend class CCoinControlWidgetItem
CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent=0)
void setModel(WalletModel *model)
static void updateLabels(WalletModel *, QDialog *)
const PlatformStyle * platformStyle
QAction * copyTransactionHashAction
Ui::CoinControlDialog * ui
void sortView(int, Qt::SortOrder)
static CCoinControl * coinControl
void showMenu(const QPoint &)
void copyTransactionHash()
void viewItemChanged(QTreeWidgetItem *, int)
void clipboardLowOutput()
void buttonSelectAllClicked()
static QList< CAmount > payAmounts
static bool fSubtractFeeFromAmount
void buttonBoxClicked(QAbstractButton *)
Interface to Bitcoin wallet from Qt view code.
void unlockCoin(COutPoint &output)
void listLockedCoins(std::vector< COutPoint > &vOutpts)
void getOutputs(const std::vector< COutPoint > &vOutpoints, std::vector< COutput > &vOutputs)
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
void lockCoin(COutPoint &output)
bool getPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
bool isLockedCoin(uint256 hash, unsigned int n) const
bool isSpent(const COutPoint &outpoint) const
void listCoins(std::map< QString, std::vector< COutput > > &mapCoins) const
std::string GetHex() const
static CAmount GetRequiredFee(const CMutableTransaction &tx, unsigned int nTxBytes)
Return the minimum required fee taking into account the floating relay fee and user set minimum trans...
static CAmount GetMinimumFee(const CMutableTransaction &tx, unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool &pool)
Estimate the minimum fee considering user set parameters and the required fee.
int64_t GetTxTime() const
QString dateTimeStr(const QDateTime &date)
void setClipboard(const QString &str)
bool operator<(const CNetAddr &a, const CNetAddr &b)
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
A mutable version of CTransaction.
std::vector< CTxOut > vout
double AllowFreeThreshold()
uint256 uint256S(const char *str)
#define PAIRTYPE(t1, t2)
This is needed because the foreach macro can't get over the comma in pair<t1, t2>
CTxMemPool mempool(::minRelayTxFee)
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE)
Transaction fee set by the user.
unsigned int nTxConfirmTarget
bool fSendFreeTransactions