Browse Source
0.106a86c24
Coin Control Features (Cozz Lovan)8dfd8c6
pass nBytes as parameter to GetMinFee(..) (Cozz Lovan)
Wladimir J. van der Laan
11 years ago
25 changed files with 2562 additions and 48 deletions
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
#ifndef COINCONTROL_H |
||||
#define COINCONTROL_H |
||||
|
||||
#include "core.h" |
||||
|
||||
/** Coin Control Features. */ |
||||
class CCoinControl |
||||
{ |
||||
public: |
||||
CTxDestination destChange; |
||||
|
||||
CCoinControl() |
||||
{ |
||||
SetNull(); |
||||
} |
||||
|
||||
void SetNull() |
||||
{ |
||||
destChange = CNoDestination(); |
||||
setSelected.clear(); |
||||
} |
||||
|
||||
bool HasSelected() const |
||||
{ |
||||
return (setSelected.size() > 0); |
||||
} |
||||
|
||||
bool IsSelected(const uint256& hash, unsigned int n) const |
||||
{ |
||||
COutPoint outpt(hash, n); |
||||
return (setSelected.count(outpt) > 0); |
||||
} |
||||
|
||||
void Select(COutPoint& output) |
||||
{ |
||||
setSelected.insert(output); |
||||
} |
||||
|
||||
void UnSelect(COutPoint& output) |
||||
{ |
||||
setSelected.erase(output); |
||||
} |
||||
|
||||
void UnSelectAll() |
||||
{ |
||||
setSelected.clear(); |
||||
} |
||||
|
||||
void ListSelected(std::vector<COutPoint>& vOutpoints) |
||||
{ |
||||
vOutpoints.assign(setSelected.begin(), setSelected.end()); |
||||
} |
||||
|
||||
private: |
||||
std::set<COutPoint> setSelected; |
||||
|
||||
}; |
||||
|
||||
#endif // COINCONTROL_H
|
@ -0,0 +1,766 @@
@@ -0,0 +1,766 @@
|
||||
#include "coincontroldialog.h" |
||||
#include "ui_coincontroldialog.h" |
||||
|
||||
#include "init.h" |
||||
#include "bitcoinunits.h" |
||||
#include "walletmodel.h" |
||||
#include "addresstablemodel.h" |
||||
#include "optionsmodel.h" |
||||
#include "guiutil.h" |
||||
#include "coincontrol.h" |
||||
#include "main.h" |
||||
#include "wallet.h" |
||||
|
||||
#include <QApplication> |
||||
#include <QCheckBox> |
||||
#include <QClipboard> |
||||
#include <QColor> |
||||
#include <QCursor> |
||||
#include <QDateTime> |
||||
#include <QDialogButtonBox> |
||||
#include <QFlags> |
||||
#include <QIcon> |
||||
#include <QString> |
||||
#include <QTreeWidget> |
||||
#include <QTreeWidgetItem> |
||||
|
||||
using namespace std; |
||||
QList<qint64> CoinControlDialog::payAmounts; |
||||
CCoinControl* CoinControlDialog::coinControl = new CCoinControl(); |
||||
|
||||
CoinControlDialog::CoinControlDialog(QWidget *parent) : |
||||
QDialog(parent), |
||||
ui(new Ui::CoinControlDialog), |
||||
model(0) |
||||
{ |
||||
ui->setupUi(this); |
||||
|
||||
// context menu actions
|
||||
QAction *copyAddressAction = new QAction(tr("Copy address"), this); |
||||
QAction *copyLabelAction = new QAction(tr("Copy label"), this); |
||||
QAction *copyAmountAction = new QAction(tr("Copy amount"), this); |
||||
copyTransactionHashAction = new QAction(tr("Copy transaction ID"), this); // we need to enable/disable this
|
||||
lockAction = new QAction(tr("Lock unspent"), this); // we need to enable/disable this
|
||||
unlockAction = new QAction(tr("Unlock unspent"), this); // we need to enable/disable this
|
||||
|
||||
// context menu
|
||||
contextMenu = new QMenu(); |
||||
contextMenu->addAction(copyAddressAction); |
||||
contextMenu->addAction(copyLabelAction); |
||||
contextMenu->addAction(copyAmountAction); |
||||
contextMenu->addAction(copyTransactionHashAction); |
||||
contextMenu->addSeparator(); |
||||
contextMenu->addAction(lockAction); |
||||
contextMenu->addAction(unlockAction); |
||||
|
||||
// context menu signals
|
||||
connect(ui->treeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showMenu(QPoint))); |
||||
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress())); |
||||
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel())); |
||||
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); |
||||
connect(copyTransactionHashAction, SIGNAL(triggered()), this, SLOT(copyTransactionHash())); |
||||
connect(lockAction, SIGNAL(triggered()), this, SLOT(lockCoin())); |
||||
connect(unlockAction, SIGNAL(triggered()), this, SLOT(unlockCoin())); |
||||
|
||||
// clipboard actions
|
||||
QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); |
||||
QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); |
||||
QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); |
||||
QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); |
||||
QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); |
||||
QAction *clipboardPriorityAction = new QAction(tr("Copy priority"), this); |
||||
QAction *clipboardLowOutputAction = new QAction(tr("Copy low output"), this); |
||||
QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); |
||||
|
||||
connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(clipboardQuantity())); |
||||
connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(clipboardAmount())); |
||||
connect(clipboardFeeAction, SIGNAL(triggered()), this, SLOT(clipboardFee())); |
||||
connect(clipboardAfterFeeAction, SIGNAL(triggered()), this, SLOT(clipboardAfterFee())); |
||||
connect(clipboardBytesAction, SIGNAL(triggered()), this, SLOT(clipboardBytes())); |
||||
connect(clipboardPriorityAction, SIGNAL(triggered()), this, SLOT(clipboardPriority())); |
||||
connect(clipboardLowOutputAction, SIGNAL(triggered()), this, SLOT(clipboardLowOutput())); |
||||
connect(clipboardChangeAction, SIGNAL(triggered()), this, SLOT(clipboardChange())); |
||||
|
||||
ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); |
||||
ui->labelCoinControlAmount->addAction(clipboardAmountAction); |
||||
ui->labelCoinControlFee->addAction(clipboardFeeAction); |
||||
ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); |
||||
ui->labelCoinControlBytes->addAction(clipboardBytesAction); |
||||
ui->labelCoinControlPriority->addAction(clipboardPriorityAction); |
||||
ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); |
||||
ui->labelCoinControlChange->addAction(clipboardChangeAction); |
||||
|
||||
// toggle tree/list mode
|
||||
connect(ui->radioTreeMode, SIGNAL(toggled(bool)), this, SLOT(radioTreeMode(bool))); |
||||
connect(ui->radioListMode, SIGNAL(toggled(bool)), this, SLOT(radioListMode(bool))); |
||||
|
||||
// click on checkbox
|
||||
connect(ui->treeWidget, SIGNAL(itemChanged( QTreeWidgetItem*, int)), this, SLOT(viewItemChanged( QTreeWidgetItem*, int))); |
||||
|
||||
// click on header
|
||||
ui->treeWidget->header()->setClickable(true); |
||||
connect(ui->treeWidget->header(), SIGNAL(sectionClicked(int)), this, SLOT(headerSectionClicked(int))); |
||||
|
||||
// ok button
|
||||
connect(ui->buttonBox, SIGNAL(clicked( QAbstractButton*)), this, SLOT(buttonBoxClicked(QAbstractButton*))); |
||||
|
||||
// (un)select all
|
||||
connect(ui->pushButtonSelectAll, SIGNAL(clicked()), this, SLOT(buttonSelectAllClicked())); |
||||
|
||||
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84); |
||||
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 100); |
||||
ui->treeWidget->setColumnWidth(COLUMN_LABEL, 170); |
||||
ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 290); |
||||
ui->treeWidget->setColumnWidth(COLUMN_DATE, 110); |
||||
ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 100); |
||||
ui->treeWidget->setColumnWidth(COLUMN_PRIORITY, 100); |
||||
ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transacton hash in this column, but dont show it
|
||||
ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but dont show it
|
||||
ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64 in this column, but dont show it
|
||||
ui->treeWidget->setColumnHidden(COLUMN_PRIORITY_INT64, true); // store priority int64 in this column, but dont show it
|
||||
|
||||
// default view is sorted by amount desc
|
||||
sortView(COLUMN_AMOUNT_INT64, Qt::DescendingOrder); |
||||
} |
||||
|
||||
CoinControlDialog::~CoinControlDialog() |
||||
{ |
||||
delete ui; |
||||
} |
||||
|
||||
void CoinControlDialog::setModel(WalletModel *model) |
||||
{ |
||||
this->model = model; |
||||
|
||||
if(model && model->getOptionsModel() && model->getAddressTableModel()) |
||||
{ |
||||
updateView(); |
||||
updateLabelLocked(); |
||||
CoinControlDialog::updateLabels(model, this); |
||||
} |
||||
} |
||||
|
||||
// helper function str_pad
|
||||
QString CoinControlDialog::strPad(QString s, int nPadLength, QString sPadding) |
||||
{ |
||||
while (s.length() < nPadLength) |
||||
s = sPadding + s; |
||||
|
||||
return s; |
||||
} |
||||
|
||||
// ok button
|
||||
void CoinControlDialog::buttonBoxClicked(QAbstractButton* button) |
||||
{ |
||||
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) |
||||
done(QDialog::Accepted); // closes the dialog
|
||||
} |
||||
|
||||
// (un)select all
|
||||
void CoinControlDialog::buttonSelectAllClicked() |
||||
{ |
||||
Qt::CheckState state = Qt::Checked; |
||||
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) |
||||
{ |
||||
if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) != Qt::Unchecked) |
||||
{ |
||||
state = Qt::Unchecked; |
||||
break; |
||||
} |
||||
} |
||||
ui->treeWidget->setEnabled(false); |
||||
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) |
||||
if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) != state) |
||||
ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX, state); |
||||
ui->treeWidget->setEnabled(true); |
||||
if (state == Qt::Unchecked) |
||||
coinControl->UnSelectAll(); // just to be sure
|
||||
CoinControlDialog::updateLabels(model, this); |
||||
} |
||||
|
||||
// context menu
|
||||
void CoinControlDialog::showMenu(const QPoint &point) |
||||
{ |
||||
QTreeWidgetItem *item = ui->treeWidget->itemAt(point); |
||||
if(item) |
||||
{ |
||||
contextMenuItem = item; |
||||
|
||||
// disable some items (like Copy Transaction ID, lock, unlock) for tree roots in context menu
|
||||
if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode)
|
||||
{ |
||||
copyTransactionHashAction->setEnabled(true); |
||||
if (model->isLockedCoin(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) |
||||
{ |
||||
lockAction->setEnabled(false); |
||||
unlockAction->setEnabled(true); |
||||
} |
||||
else |
||||
{ |
||||
lockAction->setEnabled(true); |
||||
unlockAction->setEnabled(false); |
||||
} |
||||
} |
||||
else // this means click on parent node in tree mode -> disable all
|
||||
{ |
||||
copyTransactionHashAction->setEnabled(false); |
||||
lockAction->setEnabled(false); |
||||
unlockAction->setEnabled(false); |
||||
} |
||||
|
||||
// show context menu
|
||||
contextMenu->exec(QCursor::pos()); |
||||
} |
||||
} |
||||
|
||||
// context menu action: copy amount
|
||||
void CoinControlDialog::copyAmount() |
||||
{ |
||||
GUIUtil::setClipboard(contextMenuItem->text(COLUMN_AMOUNT)); |
||||
} |
||||
|
||||
// context menu action: copy label
|
||||
void CoinControlDialog::copyLabel() |
||||
{ |
||||
if (ui->radioTreeMode->isChecked() && contextMenuItem->text(COLUMN_LABEL).length() == 0 && contextMenuItem->parent()) |
||||
GUIUtil::setClipboard(contextMenuItem->parent()->text(COLUMN_LABEL)); |
||||
else |
||||
GUIUtil::setClipboard(contextMenuItem->text(COLUMN_LABEL)); |
||||
} |
||||
|
||||
// context menu action: copy address
|
||||
void CoinControlDialog::copyAddress() |
||||
{ |
||||
if (ui->radioTreeMode->isChecked() && contextMenuItem->text(COLUMN_ADDRESS).length() == 0 && contextMenuItem->parent()) |
||||
GUIUtil::setClipboard(contextMenuItem->parent()->text(COLUMN_ADDRESS)); |
||||
else |
||||
GUIUtil::setClipboard(contextMenuItem->text(COLUMN_ADDRESS)); |
||||
} |
||||
|
||||
// context menu action: copy transaction id
|
||||
void CoinControlDialog::copyTransactionHash() |
||||
{ |
||||
GUIUtil::setClipboard(contextMenuItem->text(COLUMN_TXHASH)); |
||||
} |
||||
|
||||
// context menu action: lock coin
|
||||
void CoinControlDialog::lockCoin() |
||||
{ |
||||
if (contextMenuItem->checkState(COLUMN_CHECKBOX) == Qt::Checked) |
||||
contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); |
||||
|
||||
COutPoint outpt(uint256(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); |
||||
model->lockCoin(outpt); |
||||
contextMenuItem->setDisabled(true); |
||||
contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed")); |
||||
updateLabelLocked(); |
||||
} |
||||
|
||||
// context menu action: unlock coin
|
||||
void CoinControlDialog::unlockCoin() |
||||
{ |
||||
COutPoint outpt(uint256(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); |
||||
model->unlockCoin(outpt); |
||||
contextMenuItem->setDisabled(false); |
||||
contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon()); |
||||
updateLabelLocked(); |
||||
} |
||||
|
||||
// copy label "Quantity" to clipboard
|
||||
void CoinControlDialog::clipboardQuantity() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlQuantity->text()); |
||||
} |
||||
|
||||
// copy label "Amount" to clipboard
|
||||
void CoinControlDialog::clipboardAmount() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" "))); |
||||
} |
||||
|
||||
// copy label "Fee" to clipboard
|
||||
void CoinControlDialog::clipboardFee() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" "))); |
||||
} |
||||
|
||||
// copy label "After fee" to clipboard
|
||||
void CoinControlDialog::clipboardAfterFee() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" "))); |
||||
} |
||||
|
||||
// copy label "Bytes" to clipboard
|
||||
void CoinControlDialog::clipboardBytes() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlBytes->text()); |
||||
} |
||||
|
||||
// copy label "Priority" to clipboard
|
||||
void CoinControlDialog::clipboardPriority() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlPriority->text()); |
||||
} |
||||
|
||||
// copy label "Low output" to clipboard
|
||||
void CoinControlDialog::clipboardLowOutput() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text()); |
||||
} |
||||
|
||||
// copy label "Change" to clipboard
|
||||
void CoinControlDialog::clipboardChange() |
||||
{ |
||||
GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" "))); |
||||
} |
||||
|
||||
// treeview: sort
|
||||
void CoinControlDialog::sortView(int column, Qt::SortOrder order) |
||||
{ |
||||
sortColumn = column; |
||||
sortOrder = order; |
||||
ui->treeWidget->sortItems(column, order); |
||||
ui->treeWidget->header()->setSortIndicator((sortColumn == COLUMN_AMOUNT_INT64 ? COLUMN_AMOUNT : (sortColumn == COLUMN_PRIORITY_INT64 ? COLUMN_PRIORITY : sortColumn)), sortOrder); |
||||
} |
||||
|
||||
// treeview: clicked on header
|
||||
void CoinControlDialog::headerSectionClicked(int logicalIndex) |
||||
{ |
||||
if (logicalIndex == COLUMN_CHECKBOX) // click on most left column -> do nothing
|
||||
{ |
||||
ui->treeWidget->header()->setSortIndicator((sortColumn == COLUMN_AMOUNT_INT64 ? COLUMN_AMOUNT : (sortColumn == COLUMN_PRIORITY_INT64 ? COLUMN_PRIORITY : sortColumn)), sortOrder); |
||||
} |
||||
else |
||||
{ |
||||
if (logicalIndex == COLUMN_AMOUNT) // sort by amount
|
||||
logicalIndex = COLUMN_AMOUNT_INT64; |
||||
|
||||
if (logicalIndex == COLUMN_PRIORITY) // sort by priority
|
||||
logicalIndex = COLUMN_PRIORITY_INT64; |
||||
|
||||
if (sortColumn == logicalIndex) |
||||
sortOrder = ((sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder); |
||||
else |
||||
{ |
||||
sortColumn = logicalIndex; |
||||
sortOrder = ((sortColumn == COLUMN_AMOUNT_INT64 || sortColumn == COLUMN_PRIORITY_INT64 || sortColumn == COLUMN_DATE || sortColumn == COLUMN_CONFIRMATIONS) ? Qt::DescendingOrder : Qt::AscendingOrder); // if amount,date,conf,priority then default => desc, else default => asc
|
||||
} |
||||
|
||||
sortView(sortColumn, sortOrder); |
||||
} |
||||
} |
||||
|
||||
// toggle tree mode
|
||||
void CoinControlDialog::radioTreeMode(bool checked) |
||||
{ |
||||
if (checked && model) |
||||
updateView(); |
||||
} |
||||
|
||||
// toggle list mode
|
||||
void CoinControlDialog::radioListMode(bool checked) |
||||
{ |
||||
if (checked && model) |
||||
updateView(); |
||||
} |
||||
|
||||
// checkbox clicked by user
|
||||
void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) |
||||
{ |
||||
if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode)
|
||||
{ |
||||
COutPoint outpt(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()); |
||||
|
||||
if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) |
||||
coinControl->UnSelect(outpt); |
||||
else if (item->isDisabled()) // locked (this happens if "check all" through parent node)
|
||||
item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); |
||||
else |
||||
coinControl->Select(outpt); |
||||
|
||||
// selection changed -> update labels
|
||||
if (ui->treeWidget->isEnabled()) // do not update on every click for (un)select all
|
||||
CoinControlDialog::updateLabels(model, this); |
||||
} |
||||
} |
||||
|
||||
// return human readable label for priority number
|
||||
QString CoinControlDialog::getPriorityLabel(double dPriority) |
||||
{ |
||||
if (AllowFree(dPriority)) // at least medium
|
||||
{ |
||||
if (AllowFree(dPriority / 1000000)) return tr("highest"); |
||||
else if (AllowFree(dPriority / 100000)) return tr("higher"); |
||||
else if (AllowFree(dPriority / 10000)) return tr("high"); |
||||
else if (AllowFree(dPriority / 1000)) return tr("medium-high"); |
||||
else return tr("medium"); |
||||
} |
||||
else |
||||
{ |
||||
if (AllowFree(dPriority * 10)) return tr("low-medium"); |
||||
else if (AllowFree(dPriority * 100)) return tr("low"); |
||||
else if (AllowFree(dPriority * 1000)) return tr("lower"); |
||||
else return tr("lowest"); |
||||
} |
||||
} |
||||
|
||||
// shows count of locked unspent outputs
|
||||
void CoinControlDialog::updateLabelLocked() |
||||
{ |
||||
vector<COutPoint> vOutpts; |
||||
model->listLockedCoins(vOutpts); |
||||
if (vOutpts.size() > 0) |
||||
{ |
||||
ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size())); |
||||
ui->labelLocked->setVisible(true); |
||||
} |
||||
else ui->labelLocked->setVisible(false); |
||||
} |
||||
|
||||
void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) |
||||
{ |
||||
if (!model) return; |
||||
|
||||
// nPayAmount
|
||||
qint64 nPayAmount = 0; |
||||
bool fLowOutput = false; |
||||
bool fDust = false; |
||||
CTransaction txDummy; |
||||
foreach(const qint64 &amount, CoinControlDialog::payAmounts) |
||||
{ |
||||
nPayAmount += amount; |
||||
|
||||
if (amount > 0) |
||||
{ |
||||
if (amount < CENT) |
||||
fLowOutput = true; |
||||
|
||||
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0)); |
||||
txDummy.vout.push_back(txout); |
||||
if (txout.IsDust(CTransaction::nMinRelayTxFee)) |
||||
fDust = true; |
||||
} |
||||
} |
||||
|
||||
QString sPriorityLabel = ""; |
||||
int64_t nAmount = 0; |
||||
int64_t nPayFee = 0; |
||||
int64_t nAfterFee = 0; |
||||
int64_t nChange = 0; |
||||
unsigned int nBytes = 0; |
||||
unsigned int nBytesInputs = 0; |
||||
double dPriority = 0; |
||||
double dPriorityInputs = 0; |
||||
unsigned int nQuantity = 0; |
||||
int nQuantityUncompressed = 0; |
||||
|
||||
vector<COutPoint> vCoinControl; |
||||
vector<COutput> vOutputs; |
||||
coinControl->ListSelected(vCoinControl); |
||||
model->getOutputs(vCoinControl, vOutputs); |
||||
|
||||
BOOST_FOREACH(const COutput& out, vOutputs) |
||||
{ |
||||
// unselect already spent, very unlikely scenario, this could happen when selected are spent elsewhere, like rpc or another computer
|
||||
if (out.tx->IsSpent(out.i)) |
||||
{ |
||||
uint256 txhash = out.tx->GetHash(); |
||||
COutPoint outpt(txhash, out.i); |
||||
coinControl->UnSelect(outpt); |
||||
continue; |
||||
} |
||||
|
||||
// Quantity
|
||||
nQuantity++; |
||||
|
||||
// Amount
|
||||
nAmount += out.tx->vout[out.i].nValue; |
||||
|
||||
// Priority
|
||||
dPriorityInputs += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); |
||||
|
||||
// Bytes
|
||||
CTxDestination address; |
||||
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) |
||||
{ |
||||
CPubKey pubkey; |
||||
CKeyID *keyid = boost::get<CKeyID>(&address); |
||||
if (keyid && model->getPubKey(*keyid, pubkey)) |
||||
{ |
||||
nBytesInputs += (pubkey.IsCompressed() ? 148 : 180); |
||||
if (!pubkey.IsCompressed()) |
||||
nQuantityUncompressed++; |
||||
} |
||||
else |
||||
nBytesInputs += 148; // in all error cases, simply assume 148 here
|
||||
} |
||||
else nBytesInputs += 148; |
||||
} |
||||
|
||||
// calculation
|
||||
if (nQuantity > 0) |
||||
{ |
||||
// Bytes
|
||||
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here
|
||||
|
||||
// Priority
|
||||
dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority)
|
||||
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); |
||||
|
||||
// Fee
|
||||
int64_t nFee = nTransactionFee * (1 + (int64_t)nBytes / 1000); |
||||
|
||||
// Min Fee
|
||||
int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND); |
||||
|
||||
nPayFee = max(nFee, nMinFee); |
||||
|
||||
if (nPayAmount > 0) |
||||
{ |
||||
nChange = nAmount - nPayFee - nPayAmount; |
||||
|
||||
// if sub-cent change is required, the fee must be raised to at least CTransaction::nMinTxFee
|
||||
if (nPayFee < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT) |
||||
{ |
||||
if (nChange < CTransaction::nMinTxFee) // change < 0.0001 => simply move all change to fees
|
||||
{ |
||||
nPayFee += nChange; |
||||
nChange = 0; |
||||
} |
||||
else |
||||
{ |
||||
nChange = nChange + nPayFee - CTransaction::nMinTxFee; |
||||
nPayFee = CTransaction::nMinTxFee; |
||||
} |
||||
} |
||||
|
||||
// Never create dust outputs; if we would, just add the dust to the fee.
|
||||
if (nChange > 0 && nChange < CENT) |
||||
{ |
||||
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0)); |
||||
if (txout.IsDust(CTransaction::nMinRelayTxFee)) |
||||
{ |
||||
nPayFee += nChange; |
||||
nChange = 0; |
||||
} |
||||
} |
||||
|
||||
if (nChange == 0) |
||||
nBytes -= 34; |
||||
} |
||||
|
||||
// after fee
|
||||
nAfterFee = nAmount - nPayFee; |
||||
if (nAfterFee < 0) |
||||
nAfterFee = 0; |
||||
} |
||||
|
||||
// actually update labels
|
||||
int nDisplayUnit = BitcoinUnits::BTC; |
||||
if (model && model->getOptionsModel()) |
||||
nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); |
||||
|
||||
QLabel *l1 = dialog->findChild<QLabel *>("labelCoinControlQuantity"); |
||||
QLabel *l2 = dialog->findChild<QLabel *>("labelCoinControlAmount"); |
||||
QLabel *l3 = dialog->findChild<QLabel *>("labelCoinControlFee"); |
||||
QLabel *l4 = dialog->findChild<QLabel *>("labelCoinControlAfterFee"); |
||||
QLabel *l5 = dialog->findChild<QLabel *>("labelCoinControlBytes"); |
||||
QLabel *l6 = dialog->findChild<QLabel *>("labelCoinControlPriority"); |
||||
QLabel *l7 = dialog->findChild<QLabel *>("labelCoinControlLowOutput"); |
||||
QLabel *l8 = dialog->findChild<QLabel *>("labelCoinControlChange"); |
||||
|
||||
// enable/disable "low output" and "change"
|
||||
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0); |
||||
dialog->findChild<QLabel *>("labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0); |
||||
dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setEnabled(nPayAmount > 0); |
||||
dialog->findChild<QLabel *>("labelCoinControlChange") ->setEnabled(nPayAmount > 0); |
||||
|
||||
// stats
|
||||
l1->setText(QString::number(nQuantity)); // Quantity
|
||||
l2->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAmount)); // Amount
|
||||
l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee)); // Fee
|
||||
l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee
|
||||
l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes
|
||||
l6->setText(sPriorityLabel); // Priority
|
||||
l7->setText((fLowOutput ? (fDust ? tr("DUST") : tr("yes")) : tr("no"))); // Low Output / Dust
|
||||
l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change
|
||||
|
||||
// turn labels "red"
|
||||
l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000
|
||||
l6->setStyleSheet((!AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium"
|
||||
l7->setStyleSheet((fLowOutput) ? "color:red;" : ""); // Low Output = "yes"
|
||||
l8->setStyleSheet((nChange > 0 && nChange < CENT) ? "color:red;" : ""); // Change < 0.01BTC
|
||||
|
||||
// tool tips
|
||||
l5->setToolTip(tr("This label turns red, if the transaction size is bigger than 1000 bytes.\n\n This means a fee of at least %1 per kb is required.\n\n Can vary +/- 1 Byte per input.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee))); |
||||
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))); |
||||
l7->setToolTip(tr("This label turns red, if any recipient receives an amount smaller than %1.\n\n This means a fee of at least %2 is required. \n\n Amounts below 0.546 times the minimum relay fee are shown as DUST.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee))); |
||||
l8->setToolTip(tr("This label turns red, if the change is smaller than %1.\n\n This means a fee of at least %2 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::nMinTxFee))); |
||||
dialog->findChild<QLabel *>("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); |
||||
dialog->findChild<QLabel *>("labelCoinControlPriorityText") ->setToolTip(l6->toolTip()); |
||||
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); |
||||
dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); |
||||
|
||||
// Insufficient funds
|
||||
QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds"); |
||||
if (label) |
||||
label->setVisible(nChange < 0); |
||||
} |
||||
|
||||
void CoinControlDialog::updateView() |
||||
{ |
||||
bool treeMode = ui->radioTreeMode->isChecked(); |
||||
|
||||
ui->treeWidget->clear(); |
||||
ui->treeWidget->setEnabled(false); // performance, otherwise updateLabels would be called for every checked checkbox
|
||||
ui->treeWidget->setAlternatingRowColors(!treeMode); |
||||
QFlags<Qt::ItemFlag> flgCheckbox=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; |
||||
QFlags<Qt::ItemFlag> flgTristate=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; |
||||
|
||||
int nDisplayUnit = BitcoinUnits::BTC; |
||||
if (model && model->getOptionsModel()) |
||||
nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); |
||||
|
||||
map<QString, vector<COutput> > mapCoins; |
||||
model->listCoins(mapCoins); |
||||
|
||||
BOOST_FOREACH(PAIRTYPE(QString, vector<COutput>) coins, mapCoins) |
||||
{ |
||||
QTreeWidgetItem *itemWalletAddress = new QTreeWidgetItem(); |
||||
QString sWalletAddress = coins.first; |
||||
QString sWalletLabel = ""; |
||||
if (model->getAddressTableModel()) |
||||
sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress); |
||||
if (sWalletLabel.length() == 0) |
||||
sWalletLabel = tr("(no label)"); |
||||
|
||||
if (treeMode) |
||||
{ |
||||
// wallet address
|
||||
ui->treeWidget->addTopLevelItem(itemWalletAddress); |
||||
|
||||
itemWalletAddress->setFlags(flgTristate); |
||||
itemWalletAddress->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked); |
||||
|
||||
for (int i = 0; i < ui->treeWidget->columnCount(); i++) |
||||
itemWalletAddress->setBackground(i, QColor(248, 247, 246)); |
||||
|
||||
// label
|
||||
itemWalletAddress->setText(COLUMN_LABEL, sWalletLabel); |
||||
|
||||
// address
|
||||
itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress); |
||||
} |
||||
|
||||
int64_t nSum = 0; |
||||
double dPrioritySum = 0; |
||||
int nChildren = 0; |
||||
int nInputSum = 0; |
||||
BOOST_FOREACH(const COutput& out, coins.second) |
||||
{ |
||||
int nInputSize = 0; |
||||
nSum += out.tx->vout[out.i].nValue; |
||||
nChildren++; |
||||
|
||||
QTreeWidgetItem *itemOutput; |
||||
if (treeMode) itemOutput = new QTreeWidgetItem(itemWalletAddress); |
||||
else itemOutput = new QTreeWidgetItem(ui->treeWidget); |
||||
itemOutput->setFlags(flgCheckbox); |
||||
itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked); |
||||
|
||||
// address
|
||||
CTxDestination outputAddress; |
||||
QString sAddress = ""; |
||||
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress)) |
||||
{ |
||||
sAddress = CBitcoinAddress(outputAddress).ToString().c_str(); |
||||
|
||||
// if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
|
||||
if (!treeMode || (!(sAddress == sWalletAddress))) |
||||
itemOutput->setText(COLUMN_ADDRESS, sAddress); |
||||
|
||||
CPubKey pubkey; |
||||
CKeyID *keyid = boost::get<CKeyID>(&outputAddress); |
||||
if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed()) |
||||
nInputSize = 29; // 29 = 180 - 151 (public key is 180 bytes, priority free area is 151 bytes)
|
||||
} |
||||
|
||||
// label
|
||||
if (!(sAddress == sWalletAddress)) // change
|
||||
{ |
||||
// tooltip from where the change comes from
|
||||
itemOutput->setToolTip(COLUMN_LABEL, tr("change from %1 (%2)").arg(sWalletLabel).arg(sWalletAddress)); |
||||
itemOutput->setText(COLUMN_LABEL, tr("(change)")); |
||||
} |
||||
else if (!treeMode) |
||||
{ |
||||
QString sLabel = ""; |
||||
if (model->getAddressTableModel()) |
||||
sLabel = model->getAddressTableModel()->labelForAddress(sAddress); |
||||
if (sLabel.length() == 0) |
||||
sLabel = tr("(no label)"); |
||||
itemOutput->setText(COLUMN_LABEL, sLabel); |
||||
} |
||||
|
||||
// amount
|
||||
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->vout[out.i].nValue)); |
||||
itemOutput->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(out.tx->vout[out.i].nValue), 15, " ")); // padding so that sorting works correctly
|
||||
|
||||
// date
|
||||
itemOutput->setText(COLUMN_DATE, QDateTime::fromTime_t(out.tx->GetTxTime()).toString("yy-MM-dd hh:mm")); |
||||
|
||||
// confirmations
|
||||
itemOutput->setText(COLUMN_CONFIRMATIONS, strPad(QString::number(out.nDepth), 8, " ")); |
||||
|
||||
// priority
|
||||
double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10
|
||||
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority)); |
||||
itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " ")); |
||||
dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); |
||||
nInputSum += nInputSize; |
||||
|
||||
// transaction hash
|
||||
uint256 txhash = out.tx->GetHash(); |
||||
itemOutput->setText(COLUMN_TXHASH, txhash.GetHex().c_str()); |
||||
|
||||
// vout index
|
||||
itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i)); |
||||
|
||||
// disable locked coins
|
||||
if (model->isLockedCoin(txhash, out.i)) |
||||
{ |
||||
COutPoint outpt(txhash, out.i); |
||||
coinControl->UnSelect(outpt); // just to be sure
|
||||
itemOutput->setDisabled(true); |
||||
itemOutput->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed")); |
||||
} |
||||
|
||||
// set checkbox
|
||||
if (coinControl->IsSelected(txhash, out.i)) |
||||
itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Checked); |
||||
} |
||||
|
||||
// amount
|
||||
if (treeMode) |
||||
{ |
||||
dPrioritySum = dPrioritySum / (nInputSum + 78); |
||||
itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); |
||||
itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); |
||||
itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " ")); |
||||
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum)); |
||||
itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " ")); |
||||
} |
||||
} |
||||
|
||||
// expand all partially selected
|
||||
if (treeMode) |
||||
{ |
||||
for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) |
||||
if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked) |
||||
ui->treeWidget->topLevelItem(i)->setExpanded(true); |
||||
} |
||||
|
||||
// sort view
|
||||
sortView(sortColumn, sortOrder); |
||||
ui->treeWidget->setEnabled(true); |
||||
} |
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
#ifndef COINCONTROLDIALOG_H |
||||
#define COINCONTROLDIALOG_H |
||||
|
||||
#include <QAbstractButton> |
||||
#include <QAction> |
||||
#include <QDialog> |
||||
#include <QList> |
||||
#include <QMenu> |
||||
#include <QPoint> |
||||
#include <QString> |
||||
#include <QTreeWidgetItem> |
||||
|
||||
namespace Ui { |
||||
class CoinControlDialog; |
||||
} |
||||
class WalletModel; |
||||
class CCoinControl; |
||||
|
||||
class CoinControlDialog : public QDialog |
||||
{ |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
explicit CoinControlDialog(QWidget *parent = 0); |
||||
~CoinControlDialog(); |
||||
|
||||
void setModel(WalletModel *model); |
||||
|
||||
// static because also called from sendcoinsdialog
|
||||
static void updateLabels(WalletModel*, QDialog*); |
||||
static QString getPriorityLabel(double); |
||||
|
||||
static QList<qint64> payAmounts; |
||||
static CCoinControl *coinControl; |
||||
|
||||
private: |
||||
Ui::CoinControlDialog *ui; |
||||
WalletModel *model; |
||||
int sortColumn; |
||||
Qt::SortOrder sortOrder; |
||||
|
||||
QMenu *contextMenu; |
||||
QTreeWidgetItem *contextMenuItem; |
||||
QAction *copyTransactionHashAction; |
||||
QAction *lockAction; |
||||
QAction *unlockAction; |
||||
|
||||
QString strPad(QString, int, QString); |
||||
void sortView(int, Qt::SortOrder); |
||||
void updateView(); |
||||
|
||||
enum |
||||
{ |
||||
COLUMN_CHECKBOX, |
||||
COLUMN_AMOUNT, |
||||
COLUMN_LABEL, |
||||
COLUMN_ADDRESS, |
||||
COLUMN_DATE, |
||||
COLUMN_CONFIRMATIONS, |
||||
COLUMN_PRIORITY, |
||||
COLUMN_TXHASH, |
||||
COLUMN_VOUT_INDEX, |
||||
COLUMN_AMOUNT_INT64, |
||||
COLUMN_PRIORITY_INT64 |
||||
}; |
||||
|
||||
private slots: |
||||
void showMenu(const QPoint &); |
||||
void copyAmount(); |
||||
void copyLabel(); |
||||
void copyAddress(); |
||||
void copyTransactionHash(); |
||||
void lockCoin(); |
||||
void unlockCoin(); |
||||
void clipboardQuantity(); |
||||
void clipboardAmount(); |
||||
void clipboardFee(); |
||||
void clipboardAfterFee(); |
||||
void clipboardBytes(); |
||||
void clipboardPriority(); |
||||
void clipboardLowOutput(); |
||||
void clipboardChange(); |
||||
void radioTreeMode(bool); |
||||
void radioListMode(bool); |
||||
void viewItemChanged(QTreeWidgetItem*, int); |
||||
void headerSectionClicked(int); |
||||
void buttonBoxClicked(QAbstractButton*); |
||||
void buttonSelectAllClicked(); |
||||
void updateLabelLocked(); |
||||
}; |
||||
|
||||
#endif // COINCONTROLDIALOG_H
|
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
#include "coincontroltreewidget.h" |
||||
#include "coincontroldialog.h" |
||||
|
||||
CoinControlTreeWidget::CoinControlTreeWidget(QWidget *parent) : |
||||
QTreeWidget(parent) |
||||
{ |
||||
|
||||
} |
||||
|
||||
void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event) |
||||
{ |
||||
if (event->key() == Qt::Key_Space) // press spacebar -> select checkbox
|
||||
{ |
||||
event->ignore(); |
||||
int COLUMN_CHECKBOX = 0; |
||||
this->currentItem()->setCheckState(COLUMN_CHECKBOX, ((this->currentItem()->checkState(COLUMN_CHECKBOX) == Qt::Checked) ? Qt::Unchecked : Qt::Checked)); |
||||
} |
||||
else if (event->key() == Qt::Key_Escape) // press esc -> close dialog
|
||||
{ |
||||
event->ignore(); |
||||
CoinControlDialog *coinControlDialog = (CoinControlDialog*)this->parentWidget(); |
||||
coinControlDialog->done(QDialog::Accepted); |
||||
} |
||||
else |
||||
{ |
||||
this->QTreeWidget::keyPressEvent(event); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
#ifndef COINCONTROLTREEWIDGET_H |
||||
#define COINCONTROLTREEWIDGET_H |
||||
|
||||
#include <QKeyEvent> |
||||
#include <QTreeWidget> |
||||
|
||||
class CoinControlTreeWidget : public QTreeWidget { |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
explicit CoinControlTreeWidget(QWidget *parent = 0); |
||||
|
||||
protected: |
||||
virtual void keyPressEvent(QKeyEvent *event); |
||||
}; |
||||
|
||||
#endif // COINCONTROLTREEWIDGET_H
|
@ -0,0 +1,556 @@
@@ -0,0 +1,556 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<ui version="4.0"> |
||||
<class>CoinControlDialog</class> |
||||
<widget class="QDialog" name="CoinControlDialog"> |
||||
<property name="geometry"> |
||||
<rect> |
||||
<x>0</x> |
||||
<y>0</y> |
||||
<width>1000</width> |
||||
<height>500</height> |
||||
</rect> |
||||
</property> |
||||
<property name="windowTitle"> |
||||
<string>Coin Control</string> |
||||
</property> |
||||
<layout class="QVBoxLayout" name="verticalLayout"> |
||||
<item> |
||||
<layout class="QHBoxLayout" name="horizontalLayoutTop" stretch="0,0,0,0"> |
||||
<property name="topMargin"> |
||||
<number>0</number> |
||||
</property> |
||||
<property name="bottomMargin"> |
||||
<number>10</number> |
||||
</property> |
||||
<item> |
||||
<layout class="QFormLayout" name="formLayoutCoinControl1"> |
||||
<property name="horizontalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="verticalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="leftMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<property name="rightMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<item row="0" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlQuantityText"> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Quantity:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="0" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlQuantity"> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string notr="true">0</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlBytesText"> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Bytes:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlBytes"> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string notr="true">0</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</item> |
||||
<item> |
||||
<layout class="QFormLayout" name="formLayoutCoinControl2"> |
||||
<property name="horizontalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="verticalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="leftMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<property name="rightMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<item row="0" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlAmountText"> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Amount:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="0" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlAmount"> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string notr="true">0.00 BTC</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlPriorityText"> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Priority:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlPriority"> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string/> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</item> |
||||
<item> |
||||
<layout class="QFormLayout" name="formLayoutCoinControl3"> |
||||
<property name="horizontalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="verticalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="leftMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<property name="rightMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<item row="0" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlFeeText"> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Fee:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="0" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlFee"> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string notr="true">0.00 BTC</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlLowOutputText"> |
||||
<property name="enabled"> |
||||
<bool>false</bool> |
||||
</property> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Low Output:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlLowOutput"> |
||||
<property name="enabled"> |
||||
<bool>false</bool> |
||||
</property> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string>no</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</item> |
||||
<item> |
||||
<layout class="QFormLayout" name="formLayoutCoinControl4"> |
||||
<property name="horizontalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="verticalSpacing"> |
||||
<number>10</number> |
||||
</property> |
||||
<property name="leftMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<property name="rightMargin"> |
||||
<number>6</number> |
||||
</property> |
||||
<item row="0" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlAfterFeeText"> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>After Fee:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="0" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlAfterFee"> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string notr="true">0.00 BTC</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="0"> |
||||
<widget class="QLabel" name="labelCoinControlChangeText"> |
||||
<property name="enabled"> |
||||
<bool>false</bool> |
||||
</property> |
||||
<property name="styleSheet"> |
||||
<string notr="true">font-weight:bold;</string> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Change:</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item row="1" column="1"> |
||||
<widget class="QLabel" name="labelCoinControlChange"> |
||||
<property name="enabled"> |
||||
<bool>false</bool> |
||||
</property> |
||||
<property name="font"> |
||||
<font> |
||||
<family>Monospace</family> |
||||
<pointsize>10</pointsize> |
||||
</font> |
||||
</property> |
||||
<property name="cursor"> |
||||
<cursorShape>IBeamCursor</cursorShape> |
||||
</property> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::ActionsContextMenu</enum> |
||||
</property> |
||||
<property name="text"> |
||||
<string notr="true">0.00 BTC</string> |
||||
</property> |
||||
<property name="textInteractionFlags"> |
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</item> |
||||
</layout> |
||||
</item> |
||||
<item> |
||||
<widget class="QFrame" name="frame"> |
||||
<property name="minimumSize"> |
||||
<size> |
||||
<width>0</width> |
||||
<height>40</height> |
||||
</size> |
||||
</property> |
||||
<property name="frameShape"> |
||||
<enum>QFrame::StyledPanel</enum> |
||||
</property> |
||||
<property name="frameShadow"> |
||||
<enum>QFrame::Sunken</enum> |
||||
</property> |
||||
<widget class="QWidget" name="horizontalLayoutWidget"> |
||||
<property name="geometry"> |
||||
<rect> |
||||
<x>10</x> |
||||
<y>0</y> |
||||
<width>781</width> |
||||
<height>41</height> |
||||
</rect> |
||||
</property> |
||||
<layout class="QHBoxLayout" name="horizontalLayoutPanel" stretch="0,0,0,0,0"> |
||||
<property name="spacing"> |
||||
<number>14</number> |
||||
</property> |
||||
<item> |
||||
<widget class="QPushButton" name="pushButtonSelectAll"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<property name="text"> |
||||
<string>(un)select all</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item> |
||||
<widget class="QRadioButton" name="radioTreeMode"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<property name="text"> |
||||
<string>Tree mode</string> |
||||
</property> |
||||
<property name="checked"> |
||||
<bool>true</bool> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item> |
||||
<widget class="QRadioButton" name="radioListMode"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<property name="text"> |
||||
<string>List mode</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item> |
||||
<widget class="QLabel" name="labelLocked"> |
||||
<property name="text"> |
||||
<string>(1 locked)</string> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
<item> |
||||
<spacer name="horizontalSpacer"> |
||||
<property name="orientation"> |
||||
<enum>Qt::Horizontal</enum> |
||||
</property> |
||||
<property name="sizeHint" stdset="0"> |
||||
<size> |
||||
<width>40</width> |
||||
<height>20</height> |
||||
</size> |
||||
</property> |
||||
</spacer> |
||||
</item> |
||||
</layout> |
||||
</widget> |
||||
</widget> |
||||
</item> |
||||
<item> |
||||
<widget class="CoinControlTreeWidget" name="treeWidget"> |
||||
<property name="contextMenuPolicy"> |
||||
<enum>Qt::CustomContextMenu</enum> |
||||
</property> |
||||
<property name="sortingEnabled"> |
||||
<bool>false</bool> |
||||
</property> |
||||
<property name="columnCount"> |
||||
<number>11</number> |
||||
</property> |
||||
<attribute name="headerShowSortIndicator" stdset="0"> |
||||
<bool>true</bool> |
||||
</attribute> |
||||
<attribute name="headerStretchLastSection"> |
||||
<bool>false</bool> |
||||
</attribute> |
||||
<column> |
||||
<property name="text"> |
||||
<string/> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string>Amount</string> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string notr="true">Label</string> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string>Address</string> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string>Date</string> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string>Confirmations</string> |
||||
</property> |
||||
<property name="toolTip"> |
||||
<string>Confirmed</string> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string>Priority</string> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string/> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string/> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string/> |
||||
</property> |
||||
</column> |
||||
<column> |
||||
<property name="text"> |
||||
<string/> |
||||
</property> |
||||
</column> |
||||
</widget> |
||||
</item> |
||||
<item> |
||||
<widget class="QDialogButtonBox" name="buttonBox"> |
||||
<property name="sizePolicy"> |
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> |
||||
<horstretch>0</horstretch> |
||||
<verstretch>0</verstretch> |
||||
</sizepolicy> |
||||
</property> |
||||
<property name="orientation"> |
||||
<enum>Qt::Horizontal</enum> |
||||
</property> |
||||
<property name="standardButtons"> |
||||
<set>QDialogButtonBox::Ok</set> |
||||
</property> |
||||
</widget> |
||||
</item> |
||||
</layout> |
||||
</widget> |
||||
<customwidgets> |
||||
<customwidget> |
||||
<class>CoinControlTreeWidget</class> |
||||
<extends>QTreeWidget</extends> |
||||
<header>coincontroltreewidget.h</header> |
||||
</customwidget> |
||||
</customwidgets> |
||||
<resources/> |
||||
<connections/> |
||||
</ui> |
Loading…
Reference in new issue