Changeset View
Changeset View
Standalone View
Standalone View
src/qt/coincontroldialog.cpp
Show All 39 Lines | if (column == CoinControlDialog::COLUMN_AMOUNT || | ||||
column == CoinControlDialog::COLUMN_DATE || | column == CoinControlDialog::COLUMN_DATE || | ||||
column == CoinControlDialog::COLUMN_CONFIRMATIONS) { | column == CoinControlDialog::COLUMN_CONFIRMATIONS) { | ||||
return data(column, Qt::UserRole).toLongLong() < | return data(column, Qt::UserRole).toLongLong() < | ||||
other.data(column, Qt::UserRole).toLongLong(); | other.data(column, Qt::UserRole).toLongLong(); | ||||
} | } | ||||
return QTreeWidgetItem::operator<(other); | return QTreeWidgetItem::operator<(other); | ||||
} | } | ||||
CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, | CoinControlDialog::CoinControlDialog(CCoinControl &coin_control, | ||||
WalletModel *_model, | |||||
const PlatformStyle *_platformStyle, | |||||
QWidget *parent) | QWidget *parent) | ||||
: QDialog(parent), ui(new Ui::CoinControlDialog), model(nullptr), | : QDialog(parent), ui(new Ui::CoinControlDialog), | ||||
m_coin_control(coin_control), model(_model), | |||||
platformStyle(_platformStyle) { | platformStyle(_platformStyle) { | ||||
ui->setupUi(this); | ui->setupUi(this); | ||||
// context menu actions | // context menu actions | ||||
QAction *copyAddressAction = new QAction(tr("Copy address"), this); | QAction *copyAddressAction = new QAction(tr("Copy address"), this); | ||||
QAction *copyLabelAction = new QAction(tr("Copy label"), this); | QAction *copyLabelAction = new QAction(tr("Copy label"), this); | ||||
QAction *copyAmountAction = new QAction(tr("Copy amount"), this); | QAction *copyAmountAction = new QAction(tr("Copy amount"), this); | ||||
// we need to enable/disable this | // we need to enable/disable this | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | CoinControlDialog::CoinControlDialog(CCoinControl &coin_control, | ||||
if (settings.contains("nCoinControlSortColumn") && | if (settings.contains("nCoinControlSortColumn") && | ||||
settings.contains("nCoinControlSortOrder")) { | settings.contains("nCoinControlSortOrder")) { | ||||
sortView(settings.value("nCoinControlSortColumn").toInt(), | sortView(settings.value("nCoinControlSortColumn").toInt(), | ||||
(static_cast<Qt::SortOrder>( | (static_cast<Qt::SortOrder>( | ||||
settings.value("nCoinControlSortOrder").toInt()))); | settings.value("nCoinControlSortOrder").toInt()))); | ||||
} | } | ||||
GUIUtil::handleCloseWindowShortcut(this); | GUIUtil::handleCloseWindowShortcut(this); | ||||
if (_model->getOptionsModel() && _model->getAddressTableModel()) { | |||||
updateView(); | |||||
updateLabelLocked(); | |||||
CoinControlDialog::updateLabels(m_coin_control, _model, this); | |||||
} | |||||
} | } | ||||
CoinControlDialog::~CoinControlDialog() { | CoinControlDialog::~CoinControlDialog() { | ||||
QSettings settings; | QSettings settings; | ||||
settings.setValue("nCoinControlMode", ui->radioListMode->isChecked()); | settings.setValue("nCoinControlMode", ui->radioListMode->isChecked()); | ||||
settings.setValue("nCoinControlSortColumn", sortColumn); | settings.setValue("nCoinControlSortColumn", sortColumn); | ||||
settings.setValue("nCoinControlSortOrder", (int)sortOrder); | settings.setValue("nCoinControlSortOrder", (int)sortOrder); | ||||
delete ui; | delete ui; | ||||
} | } | ||||
void CoinControlDialog::setModel(WalletModel *_model) { | |||||
this->model = _model; | |||||
if (_model && _model->getOptionsModel() && _model->getAddressTableModel()) { | |||||
updateView(); | |||||
updateLabelLocked(); | |||||
CoinControlDialog::updateLabels(_model, this); | |||||
} | |||||
} | |||||
// ok button | // ok button | ||||
void CoinControlDialog::buttonBoxClicked(QAbstractButton *button) { | void CoinControlDialog::buttonBoxClicked(QAbstractButton *button) { | ||||
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { | if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { | ||||
// closes the dialog | // closes the dialog | ||||
done(QDialog::Accepted); | done(QDialog::Accepted); | ||||
} | } | ||||
} | } | ||||
Show All 13 Lines | for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) { | ||||
state) { | state) { | ||||
ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX, | ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX, | ||||
state); | state); | ||||
} | } | ||||
} | } | ||||
ui->treeWidget->setEnabled(true); | ui->treeWidget->setEnabled(true); | ||||
if (state == Qt::Unchecked) { | if (state == Qt::Unchecked) { | ||||
// just to be sure | // just to be sure | ||||
coinControl()->UnSelectAll(); | m_coin_control.UnSelectAll(); | ||||
} | } | ||||
CoinControlDialog::updateLabels(model, this); | CoinControlDialog::updateLabels(m_coin_control, model, this); | ||||
} | } | ||||
// context menu | // context menu | ||||
void CoinControlDialog::showMenu(const QPoint &point) { | void CoinControlDialog::showMenu(const QPoint &point) { | ||||
QTreeWidgetItem *item = ui->treeWidget->itemAt(point); | QTreeWidgetItem *item = ui->treeWidget->itemAt(point); | ||||
if (item) { | if (item) { | ||||
contextMenuItem = item; | contextMenuItem = item; | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | |||||
void CoinControlDialog::viewItemChanged(QTreeWidgetItem *item, int column) { | void CoinControlDialog::viewItemChanged(QTreeWidgetItem *item, int column) { | ||||
// transaction hash is 64 characters (this means it is a child node, so it | // transaction hash is 64 characters (this means it is a child node, so it | ||||
// is not a parent node in tree mode) | // is not a parent node in tree mode) | ||||
if (column == COLUMN_CHECKBOX && | if (column == COLUMN_CHECKBOX && | ||||
item->data(COLUMN_ADDRESS, TxIdRole).toString().length() == 64) { | item->data(COLUMN_ADDRESS, TxIdRole).toString().length() == 64) { | ||||
COutPoint outpoint = buildOutPoint(item); | COutPoint outpoint = buildOutPoint(item); | ||||
if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) { | if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) { | ||||
coinControl()->UnSelect(outpoint); | m_coin_control.UnSelect(outpoint); | ||||
} else if (item->isDisabled()) { | } else if (item->isDisabled()) { | ||||
// locked (this happens if "check all" through parent node) | // locked (this happens if "check all" through parent node) | ||||
item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); | item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); | ||||
} else { | } else { | ||||
coinControl()->Select(outpoint); | m_coin_control.Select(outpoint); | ||||
} | } | ||||
// selection changed -> update labels | // selection changed -> update labels | ||||
if (ui->treeWidget->isEnabled()) { | if (ui->treeWidget->isEnabled()) { | ||||
// do not update on every click for (un)select all | // do not update on every click for (un)select all | ||||
CoinControlDialog::updateLabels(model, this); | CoinControlDialog::updateLabels(m_coin_control, model, this); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// shows count of locked unspent outputs | // shows count of locked unspent outputs | ||||
void CoinControlDialog::updateLabelLocked() { | void CoinControlDialog::updateLabelLocked() { | ||||
std::vector<COutPoint> vOutpts; | std::vector<COutPoint> vOutpts; | ||||
model->wallet().listLockedCoins(vOutpts); | model->wallet().listLockedCoins(vOutpts); | ||||
if (vOutpts.size() > 0) { | if (vOutpts.size() > 0) { | ||||
ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size())); | ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size())); | ||||
ui->labelLocked->setVisible(true); | ui->labelLocked->setVisible(true); | ||||
} else { | } else { | ||||
ui->labelLocked->setVisible(false); | ui->labelLocked->setVisible(false); | ||||
} | } | ||||
} | } | ||||
void CoinControlDialog::updateLabels(WalletModel *model, QDialog *dialog) { | void CoinControlDialog::updateLabels(CCoinControl &m_coin_control, | ||||
WalletModel *model, QDialog *dialog) { | |||||
if (!model) { | if (!model) { | ||||
return; | return; | ||||
} | } | ||||
// nPayAmount | // nPayAmount | ||||
Amount nPayAmount = Amount::zero(); | Amount nPayAmount = Amount::zero(); | ||||
bool fDust = false; | bool fDust = false; | ||||
CMutableTransaction txDummy; | CMutableTransaction txDummy; | ||||
Show All 12 Lines | void CoinControlDialog::updateLabels(CCoinControl &m_coin_control, | ||||
Amount nPayFee = Amount::zero(); | Amount nPayFee = Amount::zero(); | ||||
Amount nAfterFee = Amount::zero(); | Amount nAfterFee = Amount::zero(); | ||||
Amount nChange = Amount::zero(); | Amount nChange = Amount::zero(); | ||||
unsigned int nBytes = 0; | unsigned int nBytes = 0; | ||||
unsigned int nBytesInputs = 0; | unsigned int nBytesInputs = 0; | ||||
unsigned int nQuantity = 0; | unsigned int nQuantity = 0; | ||||
std::vector<COutPoint> vCoinControl; | std::vector<COutPoint> vCoinControl; | ||||
coinControl()->ListSelected(vCoinControl); | m_coin_control.ListSelected(vCoinControl); | ||||
size_t i = 0; | size_t i = 0; | ||||
for (const auto &out : model->wallet().getCoins(vCoinControl)) { | for (const auto &out : model->wallet().getCoins(vCoinControl)) { | ||||
if (out.depth_in_main_chain < 0) { | if (out.depth_in_main_chain < 0) { | ||||
continue; | continue; | ||||
} | } | ||||
// unselect already spent, very unlikely scenario, this could happen | // unselect already spent, very unlikely scenario, this could happen | ||||
// when selected are spent elsewhere, like rpc or another computer | // when selected are spent elsewhere, like rpc or another computer | ||||
const COutPoint &output = vCoinControl[i++]; | const COutPoint &output = vCoinControl[i++]; | ||||
if (out.is_spent) { | if (out.is_spent) { | ||||
coinControl()->UnSelect(output); | m_coin_control.UnSelect(output); | ||||
continue; | continue; | ||||
} | } | ||||
// Quantity | // Quantity | ||||
nQuantity++; | nQuantity++; | ||||
// Amount | // Amount | ||||
nAmount += out.txout.nValue; | nAmount += out.txout.nValue; | ||||
Show All 31 Lines | if (nQuantity > 0) { | ||||
// accurate | // accurate | ||||
if (CoinControlDialog::fSubtractFeeFromAmount) { | if (CoinControlDialog::fSubtractFeeFromAmount) { | ||||
if (nAmount - nPayAmount == Amount::zero()) { | if (nAmount - nPayAmount == Amount::zero()) { | ||||
nBytes -= 34; | nBytes -= 34; | ||||
} | } | ||||
} | } | ||||
// Fee | // Fee | ||||
nPayFee = model->wallet().getMinimumFee(nBytes, *coinControl()); | nPayFee = model->wallet().getMinimumFee(nBytes, m_coin_control); | ||||
if (nPayAmount > Amount::zero()) { | if (nPayAmount > Amount::zero()) { | ||||
nChange = nAmount - nPayAmount; | nChange = nAmount - nPayAmount; | ||||
if (!CoinControlDialog::fSubtractFeeFromAmount) { | if (!CoinControlDialog::fSubtractFeeFromAmount) { | ||||
nChange -= nPayFee; | nChange -= nPayFee; | ||||
} | } | ||||
// Never create dust outputs; if we would, just add the dust to the | // Never create dust outputs; if we would, just add the dust to the | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | void CoinControlDialog::updateLabels(CCoinControl &m_coin_control, | ||||
// Insufficient funds | // Insufficient funds | ||||
QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds"); | QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds"); | ||||
if (label) { | if (label) { | ||||
label->setVisible(nChange < Amount::zero()); | label->setVisible(nChange < Amount::zero()); | ||||
} | } | ||||
} | } | ||||
CCoinControl *CoinControlDialog::coinControl() { | |||||
static CCoinControl coin_control; | |||||
return &coin_control; | |||||
} | |||||
COutPoint CoinControlDialog::buildOutPoint(const QTreeWidgetItem *item) { | COutPoint CoinControlDialog::buildOutPoint(const QTreeWidgetItem *item) { | ||||
TxId txid; | TxId txid; | ||||
txid.SetHex(item->data(COLUMN_ADDRESS, TxIdRole).toString().toStdString()); | txid.SetHex(item->data(COLUMN_ADDRESS, TxIdRole).toString().toStdString()); | ||||
return COutPoint(txid, item->data(COLUMN_ADDRESS, VOutRole).toUInt()); | return COutPoint(txid, item->data(COLUMN_ADDRESS, VOutRole).toUInt()); | ||||
} | } | ||||
void CoinControlDialog::updateView() { | void CoinControlDialog::updateView() { | ||||
if (!model || !model->getOptionsModel() || !model->getAddressTableModel()) { | if (!model || !model->getOptionsModel() || !model->getAddressTableModel()) { | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | for (const auto &coins : model->wallet().listCoins()) { | ||||
QString::fromStdString(output.GetTxId().GetHex())); | QString::fromStdString(output.GetTxId().GetHex())); | ||||
// vout index | // vout index | ||||
itemOutput->setData(COLUMN_ADDRESS, VOutRole, output.GetN()); | itemOutput->setData(COLUMN_ADDRESS, VOutRole, output.GetN()); | ||||
// disable locked coins | // disable locked coins | ||||
if (model->wallet().isLockedCoin(output)) { | if (model->wallet().isLockedCoin(output)) { | ||||
// just to be sure | // just to be sure | ||||
coinControl()->UnSelect(output); | m_coin_control.UnSelect(output); | ||||
itemOutput->setDisabled(true); | itemOutput->setDisabled(true); | ||||
itemOutput->setIcon( | itemOutput->setIcon( | ||||
COLUMN_CHECKBOX, | COLUMN_CHECKBOX, | ||||
platformStyle->SingleColorIcon(":/icons/lock_closed")); | platformStyle->SingleColorIcon(":/icons/lock_closed")); | ||||
} | } | ||||
// set checkbox | // set checkbox | ||||
if (coinControl()->IsSelected(output)) { | if (m_coin_control.IsSelected(output)) { | ||||
itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked); | itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked); | ||||
} | } | ||||
} | } | ||||
// amount | // amount | ||||
if (treeMode) { | if (treeMode) { | ||||
itemWalletAddress->setText(COLUMN_CHECKBOX, | itemWalletAddress->setText(COLUMN_CHECKBOX, | ||||
"(" + QString::number(nChildren) + ")"); | "(" + QString::number(nChildren) + ")"); | ||||
Show All 21 Lines |