2 #include "ui_coincontroldialog.h"
12 #include <QApplication>
18 #include <QDialogButtonBox>
22 #include <QTreeWidget>
23 #include <QTreeWidgetItem>
37 QAction *copyAddressAction =
new QAction(tr(
"Copy address"),
this);
38 QAction *copyLabelAction =
new QAction(tr(
"Copy label"),
this);
39 QAction *copyAmountAction =
new QAction(tr(
"Copy amount"),
this);
41 lockAction =
new QAction(tr(
"Lock unspent"),
this);
55 connect(
ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(
showMenu(QPoint)));
56 connect(copyAddressAction, SIGNAL(triggered()),
this, SLOT(
copyAddress()));
57 connect(copyLabelAction, SIGNAL(triggered()),
this, SLOT(
copyLabel()));
58 connect(copyAmountAction, SIGNAL(triggered()),
this, SLOT(
copyAmount()));
64 QAction *clipboardQuantityAction =
new QAction(tr(
"Copy quantity"),
this);
65 QAction *clipboardAmountAction =
new QAction(tr(
"Copy amount"),
this);
66 QAction *clipboardFeeAction =
new QAction(tr(
"Copy fee"),
this);
67 QAction *clipboardAfterFeeAction =
new QAction(tr(
"Copy after fee"),
this);
68 QAction *clipboardBytesAction =
new QAction(tr(
"Copy bytes"),
this);
69 QAction *clipboardPriorityAction =
new QAction(tr(
"Copy priority"),
this);
70 QAction *clipboardLowOutputAction =
new QAction(tr(
"Copy low output"),
this);
71 QAction *clipboardChangeAction =
new QAction(tr(
"Copy change"),
this);
73 connect(clipboardQuantityAction, SIGNAL(triggered()),
this, SLOT(
clipboardQuantity()));
74 connect(clipboardAmountAction, SIGNAL(triggered()),
this, SLOT(
clipboardAmount()));
75 connect(clipboardFeeAction, SIGNAL(triggered()),
this, SLOT(
clipboardFee()));
76 connect(clipboardAfterFeeAction, SIGNAL(triggered()),
this, SLOT(
clipboardAfterFee()));
77 connect(clipboardBytesAction, SIGNAL(triggered()),
this, SLOT(
clipboardBytes()));
78 connect(clipboardPriorityAction, SIGNAL(triggered()),
this, SLOT(
clipboardPriority()));
79 connect(clipboardLowOutputAction, SIGNAL(triggered()),
this, SLOT(
clipboardLowOutput()));
80 connect(clipboardChangeAction, SIGNAL(triggered()),
this, SLOT(
clipboardChange()));
82 ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
83 ui->labelCoinControlAmount->addAction(clipboardAmountAction);
84 ui->labelCoinControlFee->addAction(clipboardFeeAction);
85 ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
86 ui->labelCoinControlBytes->addAction(clipboardBytesAction);
87 ui->labelCoinControlPriority->addAction(clipboardPriorityAction);
88 ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
89 ui->labelCoinControlChange->addAction(clipboardChangeAction);
92 connect(
ui->radioTreeMode, SIGNAL(toggled(
bool)),
this, SLOT(
radioTreeMode(
bool)));
93 connect(
ui->radioListMode, SIGNAL(toggled(
bool)),
this, SLOT(
radioListMode(
bool)));
96 connect(
ui->treeWidget, SIGNAL(itemChanged( QTreeWidgetItem*,
int)),
this, SLOT(
viewItemChanged( QTreeWidgetItem*,
int)));
99 #if QT_VERSION < 0x050000
100 ui->treeWidget->header()->setClickable(
true);
102 ui->treeWidget->header()->setSectionsClickable(
true);
107 connect(
ui->buttonBox, SIGNAL(clicked( QAbstractButton*)),
this, SLOT(
buttonBoxClicked(QAbstractButton*)));
148 while (s.length() < nPadLength)
157 if (
ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
158 done(QDialog::Accepted);
164 Qt::CheckState
state = Qt::Checked;
165 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
167 if (
ui->treeWidget->topLevelItem(i)->checkState(
COLUMN_CHECKBOX) != Qt::Unchecked)
169 state = Qt::Unchecked;
173 ui->treeWidget->setEnabled(
false);
174 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
177 ui->treeWidget->setEnabled(
true);
178 if (state == Qt::Unchecked)
186 QTreeWidgetItem *item =
ui->treeWidget->itemAt(point);
324 ui->treeWidget->sortItems(column, order);
344 sortOrder = ((
sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder);
358 if (checked &&
model)
365 if (checked &&
model)
378 else if (item->isDisabled())
384 if (
ui->treeWidget->isEnabled())
397 else return tr(
"medium");
403 else return tr(
"lowest");
410 vector<COutPoint> vOutpts;
412 if (vOutpts.size() > 0)
414 ui->labelLocked->setText(tr(
"(%1 locked)").
arg(vOutpts.size()));
415 ui->labelLocked->setVisible(
true);
417 else ui->labelLocked->setVisible(
false);
425 qint64 nPayAmount = 0;
426 bool fLowOutput =
false;
428 unsigned int nQuantityDust = 0;
432 nPayAmount += amount;
442 txDummy.
vout.push_back(txout);
448 QString sPriorityLabel =
"";
453 unsigned int nBytes = 0;
454 unsigned int nBytesInputs = 0;
455 double dPriority = 0;
456 double dPriorityInputs = 0;
457 unsigned int nQuantity = 0;
459 vector<COutPoint> vCoinControl;
460 vector<COutput> vOutputs;
464 BOOST_FOREACH(
const COutput& out, vOutputs)
479 nAmount += out.
tx->
vout[out.
i].nValue;
482 dPriorityInputs += (double)out.
tx->
vout[out.
i].nValue * (out.
nDepth+1);
489 CKeyID *keyid = boost::get<CKeyID>(&address);
490 if (keyid && model->
getPubKey(*keyid, pubkey))
495 else nBytesInputs += 148;
505 dPriority = dPriorityInputs / nBytes;
516 nPayFee = max(nFee, nMinFee);
520 nChange = nAmount - nPayFee - nPayAmount;
526 nPayFee = CTransaction::nMinTxFee * nQuantityDust;
530 if (nPayFee < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
545 if (nChange > 0 && nChange < CENT)
547 CTxOut txout(nChange, (
CScript)vector<unsigned char>(24, 0));
560 nAfterFee = nAmount - nPayFee;
570 QLabel *l1 = dialog->findChild<QLabel *>(
"labelCoinControlQuantity");
571 QLabel *l2 = dialog->findChild<QLabel *>(
"labelCoinControlAmount");
572 QLabel *l3 = dialog->findChild<QLabel *>(
"labelCoinControlFee");
573 QLabel *l4 = dialog->findChild<QLabel *>(
"labelCoinControlAfterFee");
574 QLabel *l5 = dialog->findChild<QLabel *>(
"labelCoinControlBytes");
575 QLabel *l6 = dialog->findChild<QLabel *>(
"labelCoinControlPriority");
576 QLabel *l7 = dialog->findChild<QLabel *>(
"labelCoinControlLowOutput");
577 QLabel *l8 = dialog->findChild<QLabel *>(
"labelCoinControlChange");
580 dialog->findChild<QLabel *>(
"labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0);
581 dialog->findChild<QLabel *>(
"labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0);
582 dialog->findChild<QLabel *>(
"labelCoinControlChangeText") ->setEnabled(nPayAmount > 0);
583 dialog->findChild<QLabel *>(
"labelCoinControlChange") ->setEnabled(nPayAmount > 0);
586 l1->setText(QString::number(nQuantity));
590 l5->setText(((nBytes > 0) ?
"~" :
"") + QString::number(nBytes));
591 l6->setText(sPriorityLabel);
592 l7->setText((fLowOutput ? (fDust ? tr(
"DUST") : tr(
"yes")) : tr(
"no")));
596 l5->setStyleSheet((nBytes >= 5000) ?
"color:red;" :
"");
598 l7->setStyleSheet((fLowOutput) ?
"color:red;" :
"");
599 l8->setStyleSheet((nChange > 0 && nChange < CENT) ?
"color:red;" :
"");
603 l6->setToolTip(tr(
"Transactions with higher priority get more likely into a block.\n\nThis label turns red, if the priority is smaller than \"medium\".\n\n This means a fee of at least %1 per kb is required.").
arg(
BitcoinUnits::formatWithUnit(nDisplayUnit,
CTransaction::nMinTxFee)));
606 dialog->findChild<QLabel *>(
"labelCoinControlBytesText") ->setToolTip(l5->toolTip());
607 dialog->findChild<QLabel *>(
"labelCoinControlPriorityText") ->setToolTip(l6->toolTip());
608 dialog->findChild<QLabel *>(
"labelCoinControlLowOutputText")->setToolTip(l7->toolTip());
609 dialog->findChild<QLabel *>(
"labelCoinControlChangeText") ->setToolTip(l8->toolTip());
612 QLabel *label = dialog->findChild<QLabel *>(
"labelCoinControlInsuffFunds");
614 label->setVisible(nChange < 0);
619 bool treeMode =
ui->radioTreeMode->isChecked();
621 ui->treeWidget->clear();
622 ui->treeWidget->setEnabled(
false);
623 ui->treeWidget->setAlternatingRowColors(!treeMode);
624 QFlags<Qt::ItemFlag> flgCheckbox=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
625 QFlags<Qt::ItemFlag> flgTristate=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
631 map<QString, vector<COutput> > mapCoins;
634 BOOST_FOREACH(
PAIRTYPE(QString, vector<COutput>) coins, mapCoins)
636 QTreeWidgetItem *itemWalletAddress =
new QTreeWidgetItem();
637 QString sWalletAddress = coins.first;
638 QString sWalletLabel =
"";
641 if (sWalletLabel.length() == 0)
642 sWalletLabel = tr(
"(no label)");
647 ui->treeWidget->addTopLevelItem(itemWalletAddress);
649 itemWalletAddress->setFlags(flgTristate);
652 for (
int i = 0; i <
ui->treeWidget->columnCount(); i++)
653 itemWalletAddress->setBackground(i, QColor(248, 247, 246));
663 double dPrioritySum = 0;
666 BOOST_FOREACH(
const COutput& out, coins.second)
668 int nInputSize = 148;
669 nSum += out.
tx->
vout[out.
i].nValue;
672 QTreeWidgetItem *itemOutput;
673 if (treeMode) itemOutput =
new QTreeWidgetItem(itemWalletAddress);
674 else itemOutput =
new QTreeWidgetItem(
ui->treeWidget);
675 itemOutput->setFlags(flgCheckbox);
680 QString sAddress =
"";
686 if (!treeMode || (!(sAddress == sWalletAddress)))
690 CKeyID *keyid = boost::get<CKeyID>(&outputAddress);
696 if (!(sAddress == sWalletAddress))
699 itemOutput->setToolTip(
COLUMN_LABEL, tr(
"change from %1 (%2)").
arg(sWalletLabel).
arg(sWalletAddress));
707 if (sLabel.length() == 0)
708 sLabel = tr(
"(no label)");
723 double dPriority = ((double)out.
tx->
vout[out.
i].nValue / (nInputSize + 78)) * (out.
nDepth+1);
726 dPrioritySum += (double)out.
tx->
vout[out.
i].nValue * (out.
nDepth+1);
727 nInputSum += nInputSize;
741 itemOutput->setDisabled(
true);
753 dPrioritySum = dPrioritySum / (nInputSum + 78);
754 itemWalletAddress->setText(
COLUMN_CHECKBOX,
"(" + QString::number(nChildren) +
")");
765 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
766 if (
ui->treeWidget->topLevelItem(i)->checkState(
COLUMN_CHECKBOX) == Qt::PartiallyChecked)
767 ui->treeWidget->topLevelItem(i)->setExpanded(
true);
772 ui->treeWidget->setEnabled(
true);
void viewItemChanged(QTreeWidgetItem *, int)
void getOutputs(const std::vector< COutPoint > &vOutpoints, std::vector< COutput > &vOutputs)
void lockCoin(COutPoint &output)
void buttonSelectAllClicked()
void clipboardLowOutput()
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false)
Format as string (with unit)
void headerSectionClicked(int)
static CCoinControl * coinControl
void copyTransactionHash()
bool isLockedCoin(uint256 hash, unsigned int n) const
bool IsSpent(unsigned int nOut) const
static bool AllowFree(double dPriority)
bool IsSelected(const uint256 &hash, unsigned int n) const
AddressTableModel * getAddressTableModel()
static int64 nMinTxFee
Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) ...
QAction * copyTransactionHashAction
Ui::CoinControlDialog * ui
void setClipboard(const QString &str)
std::vector< CTxOut > vout
An encapsulated public key.
bool getPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
static QString getPriorityLabel(double)
CoinControlDialog(QWidget *parent=0)
std::string ToString() const
static void updateLabels(WalletModel *, QDialog *)
An output of a transaction.
An outpoint - a combination of a transaction hash and an index n into its vout.
std::string GetHex() const
bool IsCompressed() const
void setModel(WalletModel *model)
QTreeWidgetItem * contextMenuItem
QString labelForAddress(const QString &address) const
void listLockedCoins(std::vector< COutPoint > &vOutpts)
Serialized script, used inside transaction inputs and outputs.
Interface to Bitcoin wallet from Qt view code.
void Select(COutPoint &output)
void unlockCoin(COutPoint &output)
A reference to a CKey: the Hash160 of its serialized public key.
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
void sortView(int, Qt::SortOrder)
static QList< qint64 > payAmounts
QString strPad(QString, int, QString)
void ListSelected(std::vector< COutPoint > &vOutpoints)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
void buttonBoxClicked(QAbstractButton *)
void UnSelect(COutPoint &output)
The basic transaction that is broadcasted on the network and contained in blocks. ...
void showMenu(const QPoint &)
void listCoins(std::map< QString, std::vector< COutput > > &mapCoins) const
static QString format(int unit, qint64 amount, bool plussign=false)
Format as string.
OptionsModel * getOptionsModel()