8 #include "ui_coincontroldialog.h"
23 #include <QApplication>
26 #include <QDialogButtonBox>
30 #include <QTreeWidget>
34 int column = treeWidget()->sortColumn();
36 return data(column, Qt::UserRole).toLongLong() < other.data(column, Qt::UserRole).toLongLong();
44 forDelegation(_forDelegation)
59 },
"container-border-purple");
62 ui->labelTitle->setProperty(
"cssClass",
"text-title-dialog");
66 ui->labelCoinControlAmountText,
67 ui->labelCoinControlBytesText,
68 ui->labelCoinControlChangeText,
69 ui->labelCoinControlLowOutputText,
70 ui->labelCoinControlFeeText,
71 ui->labelCoinControlQuantityText
72 },
"text-main-purple");
76 ui->labelCoinControlAmount,
77 ui->labelCoinControlBytes,
78 ui->labelCoinControlChange,
79 ui->labelCoinControlLowOutput,
80 ui->labelCoinControlFee,
81 ui->labelCoinControlQuantity
82 },
"text-main-purple");
84 ui->groupBox_2->setProperty(
"cssClass",
"group-box");
85 ui->treeWidget->setProperty(
"cssClass",
"table-tree");
86 ui->labelLocked->setProperty(
"cssClass",
"text-main-purple");
90 ui->pushButtonOk->setProperty(
"cssClass",
"btn-primary");
93 QAction* copyAddressAction =
new QAction(tr(
"Copy address"),
this);
94 QAction* copyLabelAction =
new QAction(tr(
"Copy label"),
this);
95 QAction* copyAmountAction =
new QAction(tr(
"Copy amount"),
this);
97 lockAction =
new QAction(tr(
"Lock unspent"),
this);
121 ui->pushButtonAmount,
122 ui->pushButtonQuantity,
124 ui->pushButtonAlterFee,
126 ui->pushButtonChange,
139 if (
ui->pushButtonSelectAll->isChecked()) {
140 ui->pushButtonSelectAll->setText(tr(
"Unselect all"));
142 ui->pushButtonSelectAll->setText(tr(
"Select all"));
153 ui->treeWidget->header()->setSectionsClickable(
true);
157 connect(
ui->pushButtonOk, &QPushButton::clicked,
this, &CoinControlDialog::accept);
174 ui->treeWidget->header()->setStretchLastSection(
true);
180 if (
settings.contains(
"nCoinControlMode") && !
settings.value(
"nCoinControlMode").toBool()) {
181 ui->radioTreeMode->setChecked(
true);
182 ui->treeWidget->setRootIsDecorated(
true);
183 ui->radioTreeMode->click();
185 ui->radioListMode->setChecked(
true);
186 ui->treeWidget->setRootIsDecorated(
false);
188 if (
settings.contains(
"nCoinControlSortColumn") &&
settings.contains(
"nCoinControlSortOrder"))
189 sortView(
settings.value(
"nCoinControlSortColumn").toInt(), (
static_cast<Qt::SortOrder
>(
settings.value(
"nCoinControlSortOrder").toInt())));
195 settings.setValue(
"nCoinControlMode",
ui->radioListMode->isChecked());
205 this->
model = _model;
219 const bool fSelectAll =
ui->pushButtonSelectAll->isChecked();
220 Qt::CheckState wantedState = fSelectAll ? Qt::Checked : Qt::Unchecked;
221 ui->treeWidget->setEnabled(
false);
222 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
225 ui->treeWidget->setEnabled(
true);
237 item->setDisabled(
false);
245 item->setDisabled(
true);
253 QTreeWidgetItem* item;
254 bool treemode =
ui->treeWidget->rootIsDecorated();
255 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++) {
256 item =
ui->treeWidget->topLevelItem(i);
258 auto subItems = item->takeChildren();
259 for (
auto j : subItems) {
271 ui->treeWidget->setEnabled(
false);
273 ui->treeWidget->setEnabled(
true);
280 QTreeWidgetItem* item =
ui->treeWidget->itemAt(point);
367 inform(tr(
"Quantity Copied"));
374 inform(tr(
"Amount Copied"));
388 inform(tr(
"After Fee Copied"));
395 inform(tr(
"Bytes Copied"));
402 inform(tr(
"Dust Copied"));
409 inform(tr(
"Change Copied"));
417 ui->treeWidget->sortItems(column, order);
428 sortOrder = ((
sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder);
441 if (checked &&
model)
448 if (checked &&
model)
461 else if (item->isDisabled())
465 bool isP2CS = item->data(
COLUMN_CHECKBOX, Qt::UserRole) == QString(
"Delegated");
470 if (
ui->treeWidget->isEnabled()) {
481 ui->labelLocked->setText(tr(
"(%1 locked)").arg(nLocked));
482 ui->labelLocked->setVisible(
true);
484 ui->labelLocked->setVisible(
false);
488 static int GetCompactSize(uint64_t nSize)
492 }
else if (nSize <= std::numeric_limits<unsigned short>::max()) {
494 }
else if (nSize <= std::numeric_limits<unsigned int>::max()) {
504 std::vector<OutPointWrapper> vCoinControl;
518 int nTransIns, nShieldIns;
528 const int P2CS_OUT_SIZE = 61;
529 int nTransOuts = 0, nShieldOuts = 0;
536 bool shieldedOut = a.second;
537 if (shieldedOut) nShieldOuts++;
539 if (a.first > 0 && !t.
fDust) {
548 bool isShieldedTx = (nShieldIns + nShieldOuts > 0);
552 t.
nBytes += (GetCompactSize(nShieldIns) + GetCompactSize(nShieldOuts));
559 t.
nBytes += (GetCompactSize(nTransIns) + GetCompactSize(nTransOuts));
591 "Select PIV Outputs to Spend" :
592 "Select Shielded PIV to Spend");
608 ui->labelCoinControlLowOutputText->setEnabled(hasPayAmount);
609 ui->labelCoinControlLowOutput->setEnabled(hasPayAmount);
610 ui->labelCoinControlChangeText->setEnabled(hasPayAmount);
611 ui->labelCoinControlChange->setEnabled(hasPayAmount);
614 ui->labelCoinControlQuantity->setText(QString::number(t.
nQuantity));
618 ui->labelCoinControlBytes->setText(((t.
nBytes > 0) ?
"~" :
"") + QString::number(t.
nBytes));
619 ui->labelCoinControlLowOutput->setText(t.
fDust ? tr(
"yes") : tr(
"no"));
622 ui->labelCoinControlFee->setText(
"~" +
ui->labelCoinControlFee->text());
623 ui->labelCoinControlAfterFee->setText(
"~" +
ui->labelCoinControlAfterFee->text());
625 ui->labelCoinControlChange->setText(
"~" +
ui->labelCoinControlChange->text());
629 ui->labelCoinControlLowOutput->setStyleSheet((t.
fDust) ?
"color:red;" :
"");
632 QString toolTip3 = tr(
"This label turns red, if recipient receives an amount smaller than %1 (transparent) / %2 (shield)."
641 QString toolTip4 = tr(
"Can vary +/- %1 u%2 per input.").arg(dFeeVary).arg(
CURRENCY_UNIT.c_str());
643 ui->labelCoinControlFee->setToolTip(toolTip4);
644 ui->labelCoinControlAfterFee->setToolTip(toolTip4);
645 ui->labelCoinControlLowOutput->setToolTip(toolTip3);
646 ui->labelCoinControlChange->setToolTip(toolTip4);
647 ui->labelCoinControlFeeText->setToolTip(
ui->labelCoinControlFee->toolTip());
648 ui->labelCoinControlAfterFeeText->setToolTip(
ui->labelCoinControlAfterFee->toolTip());
649 ui->labelCoinControlBytesText->setToolTip(
ui->labelCoinControlBytes->toolTip());
650 ui->labelCoinControlLowOutputText->setToolTip(
ui->labelCoinControlLowOutput->toolTip());
651 ui->labelCoinControlChangeText->setToolTip(
ui->labelCoinControlChange->toolTip());
654 QLabel* label = findChild<QLabel*>(
"labelCoinControlInsuffFunds");
656 label->setVisible(t.
nChange < 0);
661 QFlags<Qt::ItemFlag> flgCheckbox,
662 QFlags<Qt::ItemFlag> flgTristate,
664 const QString& sWalletAddress,
666 const QString& sWalletLabel,
668 const uint32_t outIndex,
679 itemOutput->setFlags(flgCheckbox);
692 itemOutput->setToolTip(
COLUMN_LABEL, tr(
"change in %1").arg(sWalletAddress));
694 }
else if (!treeMode) {
701 itemOutput->setData(
COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong) nValue));
706 itemOutput->setData(
COLUMN_DATE, Qt::UserRole, QVariant((qlonglong) nTime));
718 bool isLockedCoin{
false};
723 itemOutput->setDisabled(
true);
733 itemOutput->setData(
COLUMN_CHECKBOX, Qt::UserRole, QString(
"Delegated"));
735 itemOutput->setIcon(
COLUMN_CHECKBOX, QIcon(
"://ic-check-cold-staking-off"));
736 itemOutput->setToolTip(
COLUMN_CHECKBOX, tr(
"delegated to %1 for cold staking").arg(*stakerAddress));
745 bool treeMode =
ui->radioTreeMode->isChecked();
746 ui->treeWidget->setRootIsDecorated(treeMode);
748 ui->treeWidget->clear();
749 ui->treeWidget->setEnabled(
false);
750 QFlags<Qt::ItemFlag> flgCheckbox = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
751 QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
755 std::map<WalletModel::ListCoinsKey, std::vector<WalletModel::ListCoinsValue>> mapCoins;
758 for (
const auto& coins : mapCoins) {
762 const QString& sWalletAddress = keys.
address;
765 if (sWalletLabel.isEmpty())
766 sWalletLabel = tr(
"(no label)");
770 ui->treeWidget->addTopLevelItem(itemWalletAddress);
772 itemWalletAddress->setFlags(flgTristate);
777 itemWalletAddress->setToolTip(
COLUMN_LABEL, sWalletLabel);
781 if (stakerAddress != nullopt) {
783 QString label = tr(
"Delegated to %1").arg(*stakerAddress);
799 nDisplayUnit, sWalletAddress, stakerAddress, sWalletLabel,
806 itemWalletAddress->setText(
COLUMN_CHECKBOX,
"(" + QString::number(nChildren) +
")");
809 itemWalletAddress->setData(
COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong) nSum));
815 for (
int i = 0; i <
ui->treeWidget->topLevelItemCount(); i++)
816 if (
ui->treeWidget->topLevelItem(i)->checkState(
COLUMN_CHECKBOX) == Qt::PartiallyChecked)
817 ui->treeWidget->topLevelItem(i)->setExpanded(
true);
829 ui->treeWidget->setEnabled(
true);
854 payAmounts.emplace_back(amount, isShieldedRecipient);
859 ui->pushButtonSelectAll->setChecked(checked);
860 ui->pushButtonSelectAll->setText(checked ? tr(
"Unselect all") : tr(
"Select All"));
int64_t CAmount
Amount in PIV (Can be negative)
bool operator<(const CBigNum &a, const CBigNum &b)
QString labelForAddress(const QString &address) const
An outpoint - a combination of a transaction hash and an index n into its vout.
static QString removeSpaces(QString text)
static QString format(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard, bool cleanRemainderZeros=true)
Format as string.
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as string (with unit)
bool IsSelected(const BaseOutPoint &output) const
unsigned int QuantitySelected() const
void Select(const BaseOutPoint &output, CAmount value=0, bool isP2CS=false)
void ListSelected(std::vector< OutPointWrapper > &vOutpoints) const
void UnSelect(const BaseOutPoint &output)
CAmount GetFeePerK() const
An outpoint - a combination of a transaction hash and an index n into its vout.
CFeeRate estimateSmartFee(int nBlocks, int *answerFoundAtBlocks=nullptr) const
Estimate fee rate needed to get into the next nBlocks If no answer can be given at nBlocks,...
void headerSectionClicked(int)
void updatePushButtonSelectAll(bool checked)
QTreeWidgetItem * contextMenuItem
CoinControlDialog(QWidget *parent=nullptr, bool _forDelegation=false)
void toggleItemLock(QTreeWidgetItem *item)
TotalAmounts getTotals() const
void loadAvailableCoin(bool treeMode, CCoinControlWidgetItem *itemWalletAddress, QFlags< Qt::ItemFlag > flgCheckbox, QFlags< Qt::ItemFlag > flgTristate, int nDisplayUnit, const QString &sWalletAddress, const Optional< QString > &stakerAddress, const QString &sWalletLabel, const uint256 &txhash, const uint32_t outIndex, const CAmount nValue, const int64_t nTime, const int nDepth, const bool isChange)
unsigned int nSelectableInputs
friend class CCoinControlWidgetItem
void setModel(WalletModel *model)
int colCheckBoxWidth_treeMode
void buttonToggleLockClicked()
CCoinControl * coinControl
QAction * copyTransactionHashAction
void inform(const QString &text)
~CoinControlDialog() override
Ui::CoinControlDialog * ui
void sortView(int, Qt::SortOrder)
void showMenu(const QPoint &)
void copyTransactionHash()
void addPayAmount(const CAmount &amount, bool isShieldedRecipient)
void viewItemChanged(QTreeWidgetItem *, int)
void clipboardLowOutput()
void buttonSelectAllClicked()
std::vector< std::pair< CAmount, bool > > payAmounts
void setText(const QString &text)
Optional< QString > stakerAddress
Interface to PIVX wallet from Qt view code.
void lockCoin(uint256 hash, unsigned int n, bool isTransparent=true)
void unlockCoin(uint256 hash, unsigned int n, bool isTransparent=true)
void listCoins(std::map< ListCoinsKey, std::vector< ListCoinsValue >> &mapCoins, bool fSelectTransparent) const
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
std::set< COutPoint > listLockedCoins()
bool isLockedCoin(uint256 hash, unsigned int n, bool isTransparent=true) const
std::set< SaplingOutPoint > listLockedNotes()
std::string GetHex() const
const std::string CURRENCY_UNIT
QString loadStyleSheet()
Load global CSS theme.
QString dateTimeStr(const QDateTime &date)
void setClipboard(const QString &str)
boost::optional< T > Optional
Substitute for C++17 std::optional.
CAmount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFeeIn)
CAmount GetShieldedDustThreshold(const CFeeRate &dustRelayFeeIn)
void setCssProperty(std::initializer_list< QWidget * > args, const QString &value)
bool openDialog(QDialog *widget, QWidget *gui)
#define SPENDDESCRIPTION_SIZE
#define CTXIN_SPEND_DUST_SIZE
#define OUTPUTDESCRIPTION_SIZE
#define CTXOUT_REGULAR_SIZE
uint256 uint256S(const char *str)
CTxMemPool mempool(::minRelayTxFee)
CAmount GetMinRelayFee(const CTransaction &tx, const CTxMemPool &pool, unsigned int nBytes)
CAmount GetRequiredFee(unsigned int nTxBytes)
Return the minimum required fee taking into account the floating relay fee and user set minimum trans...
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE)
Settings.
bool fPayAtLeastCustomFee
unsigned int nTxConfirmTarget