Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fa4e43f
commit 6593053
Showing
2 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
// Copyright (c) 2017-2020 The PIVX developers | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#include "zsvrcontroldialog.h" | ||
#include "ui_zsvrcontroldialog.h" | ||
|
||
#include "main.h" | ||
#include "walletmodel.h" | ||
#include "guiutil.h" | ||
|
||
|
||
std::set<std::string> ZSvrControlDialog::setSelectedMints; | ||
std::set<CMintMeta> ZSvrControlDialog::setMints; | ||
|
||
bool CZSvrControlWidgetItem::operator<(const QTreeWidgetItem &other) const { | ||
int column = treeWidget()->sortColumn(); | ||
if (column == ZSvrControlDialog::COLUMN_DENOMINATION || column == ZSvrControlDialog::COLUMN_VERSION || column == ZSvrControlDialog::COLUMN_CONFIRMATIONS) | ||
return data(column, Qt::UserRole).toLongLong() < other.data(column, Qt::UserRole).toLongLong(); | ||
return QTreeWidgetItem::operator<(other); | ||
} | ||
|
||
|
||
ZSvrControlDialog::ZSvrControlDialog(QWidget *parent) : | ||
QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint), | ||
ui(new Ui::ZSvrControlDialog), | ||
model(0) | ||
{ | ||
ui->setupUi(this); | ||
setMints.clear(); | ||
|
||
/* Open CSS when configured */ | ||
this->setStyleSheet(GUIUtil::loadStyleSheet()); | ||
|
||
ui->frame->setProperty("cssClass", "container-dialog"); | ||
|
||
// Title | ||
ui->labelTitle->setText(tr("Select zSVR Denominations to Spend")); | ||
ui->labelTitle->setProperty("cssClass", "text-title-dialog"); | ||
|
||
|
||
// Label Style | ||
ui->labelZSvr->setProperty("cssClass", "text-main-purple"); | ||
ui->labelZSvr_int->setProperty("cssClass", "text-main-purple"); | ||
ui->labelQuantity->setProperty("cssClass", "text-main-purple"); | ||
ui->labelQuantity_int->setProperty("cssClass", "text-main-purple"); | ||
|
||
ui->layoutAmount->setProperty("cssClass", "container-border-purple"); | ||
ui->layoutQuantity->setProperty("cssClass", "container-border-purple"); | ||
|
||
// Buttons | ||
|
||
ui->btnEsc->setText(""); | ||
ui->btnEsc->setProperty("cssClass", "ic-close"); | ||
ui->pushButtonAll->setProperty("cssClass", "btn-check"); | ||
|
||
// click on checkbox | ||
connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &ZSvrControlDialog::updateSelection); | ||
// push select/deselect all button | ||
connect(ui->pushButtonAll, &QPushButton::clicked, this, &ZSvrControlDialog::ButtonAllClicked); | ||
} | ||
|
||
ZSvrControlDialog::~ZSvrControlDialog() | ||
{ | ||
delete ui; | ||
} | ||
|
||
void ZSvrControlDialog::setModel(WalletModel *model) | ||
{ | ||
this->model = model; | ||
updateList(); | ||
} | ||
|
||
|
||
//Update the tree widget | ||
void ZSvrControlDialog::updateList() | ||
{ | ||
// need to prevent the slot from being called each time something is changed | ||
ui->treeWidget->blockSignals(true); | ||
ui->treeWidget->clear(); | ||
|
||
// add a top level item for each denomination | ||
QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; | ||
std::map<libzerocoin::CoinDenomination, int> mapDenomPosition; | ||
for (auto denom : libzerocoin::zerocoinDenomList) { | ||
CZSvrControlWidgetItem* itemDenom(new CZSvrControlWidgetItem); | ||
ui->treeWidget->addTopLevelItem(itemDenom); | ||
|
||
//keep track of where this is positioned in tree widget | ||
mapDenomPosition[denom] = ui->treeWidget->indexOfTopLevelItem(itemDenom); | ||
|
||
itemDenom->setFlags(flgTristate); | ||
itemDenom->setText(COLUMN_DENOMINATION, QString::number(denom)); | ||
itemDenom->setData(COLUMN_DENOMINATION, Qt::UserRole, QVariant((qlonglong) denom)); | ||
} | ||
|
||
// select all unused coins - including not mature and mismatching seed. Update status of coins too. | ||
std::set<CMintMeta> set; | ||
model->listZerocoinMints(set, true, false, true, true); | ||
this->setMints = set; | ||
|
||
//populate rows with mint info | ||
int nBestHeight = chainActive.Height(); | ||
for (const CMintMeta& mint : setMints) { | ||
// assign this mint to the correct denomination in the tree view | ||
libzerocoin::CoinDenomination denom = mint.denom; | ||
CZSvrControlWidgetItem *itemMint = new CZSvrControlWidgetItem(ui->treeWidget->topLevelItem(mapDenomPosition.at(denom))); | ||
|
||
// if the mint is already selected, then it needs to have the checkbox checked | ||
std::string strPubCoinHash = mint.hashPubcoin.GetHex(); | ||
|
||
if (setSelectedMints.count(strPubCoinHash)) | ||
itemMint->setCheckState(COLUMN_CHECKBOX, Qt::Checked); | ||
else | ||
itemMint->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); | ||
|
||
itemMint->setText(COLUMN_DENOMINATION, QString::number(mint.denom)); | ||
itemMint->setData(COLUMN_DENOMINATION, Qt::UserRole, QVariant((qlonglong) denom)); | ||
itemMint->setText(COLUMN_PUBCOIN, QString::fromStdString(strPubCoinHash)); | ||
itemMint->setText(COLUMN_VERSION, QString::number(mint.nVersion)); | ||
itemMint->setData(COLUMN_VERSION, Qt::UserRole, QVariant((qlonglong) mint.nVersion)); | ||
|
||
int nConfirmations = (mint.nHeight ? nBestHeight - mint.nHeight : 0); | ||
if (nConfirmations < 0) { | ||
// Sanity check | ||
nConfirmations = 0; | ||
} | ||
|
||
itemMint->setText(COLUMN_CONFIRMATIONS, QString::number(nConfirmations)); | ||
itemMint->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong) nConfirmations)); | ||
|
||
// check for maturity | ||
// Always mature, public spends doesn't require any new accumulation. | ||
bool isMature = true; | ||
//if (mapMaturityHeight.count(mint.denom)) | ||
// isMature = mint.nHeight < mapMaturityHeight.at(denom); | ||
|
||
// disable selecting this mint if it is not spendable - also display a reason why | ||
const int nRequiredConfs = Params().GetConsensus().ZC_MinMintConfirmations; | ||
bool fSpendable = isMature && nConfirmations >= nRequiredConfs && mint.isSeedCorrect; | ||
if(!fSpendable) { | ||
itemMint->setDisabled(true); | ||
itemMint->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); | ||
|
||
//if this mint is in the selection list, then remove it | ||
if (setSelectedMints.count(strPubCoinHash)) | ||
setSelectedMints.erase(strPubCoinHash); | ||
|
||
std::string strReason = ""; | ||
if(nConfirmations < nRequiredConfs) | ||
strReason = strprintf("Needs %d more confirmations", nRequiredConfs - nConfirmations); | ||
else if (model->getEncryptionStatus() == WalletModel::EncryptionStatus::Locked) | ||
strReason = "Your wallet is locked. Impossible to spend zSVR."; | ||
else if (!mint.isSeedCorrect) | ||
strReason = "The zSVR seed used to mint this zSVR is not the same as currently hold in the wallet"; | ||
else | ||
strReason = "Needs 1 more mint added to network"; | ||
|
||
itemMint->setText(COLUMN_ISSPENDABLE, QString::fromStdString(strReason)); | ||
} else { | ||
itemMint->setText(COLUMN_ISSPENDABLE, QString("Yes")); | ||
} | ||
} | ||
|
||
ui->treeWidget->blockSignals(false); | ||
updateLabels(); | ||
} | ||
|
||
// Update the list when a checkbox is clicked | ||
void ZSvrControlDialog::updateSelection(QTreeWidgetItem* item, int column) | ||
{ | ||
// only want updates from non top level items that are available to spend | ||
if (item->parent() && column == COLUMN_CHECKBOX && !item->isDisabled()){ | ||
|
||
// see if this mint is already selected in the selection list | ||
std::string strPubcoin = item->text(COLUMN_PUBCOIN).toStdString(); | ||
bool fSelected = setSelectedMints.count(strPubcoin); | ||
|
||
// set the checkbox to the proper state and add or remove the mint from the selection list | ||
if (item->checkState(COLUMN_CHECKBOX) == Qt::Checked) { | ||
if (fSelected) return; | ||
setSelectedMints.insert(strPubcoin); | ||
} else { | ||
if (!fSelected) return; | ||
setSelectedMints.erase(strPubcoin); | ||
} | ||
updateLabels(); | ||
} | ||
} | ||
|
||
// Update the Quantity and Amount display | ||
void ZSvrControlDialog::updateLabels() | ||
{ | ||
int64_t nAmount = 0; | ||
for (const CMintMeta& mint : setMints) { | ||
if (setSelectedMints.count(mint.hashPubcoin.GetHex())) | ||
nAmount += mint.denom; | ||
} | ||
|
||
//update this dialog's labels | ||
ui->labelZSvr_int->setText(QString::number(nAmount)); | ||
ui->labelQuantity_int->setText(QString::number(setSelectedMints.size())); | ||
|
||
//update PrivacyDialog labels | ||
//privacyDialog->setZPivControlLabels(nAmount, setSelectedMints.size()); | ||
} | ||
|
||
std::vector<CMintMeta> ZSvrControlDialog::GetSelectedMints() | ||
{ | ||
std::vector<CMintMeta> listReturn; | ||
for (const CMintMeta& mint : setMints) { | ||
if (setSelectedMints.count(mint.hashPubcoin.GetHex())) | ||
listReturn.emplace_back(mint); | ||
} | ||
|
||
return listReturn; | ||
} | ||
|
||
// select or deselect all of the mints | ||
void ZSvrControlDialog::ButtonAllClicked() | ||
{ | ||
ui->treeWidget->blockSignals(true); | ||
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; | ||
} | ||
} | ||
|
||
//much quicker to start from scratch than to have QT go through all the objects and update | ||
ui->treeWidget->clear(); | ||
|
||
if (state == Qt::Checked) { | ||
for(const CMintMeta& mint : setMints) | ||
setSelectedMints.insert(mint.hashPubcoin.GetHex()); | ||
} else { | ||
setSelectedMints.clear(); | ||
} | ||
|
||
updateList(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright (c) 2017-2020 The PIVX developers | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#ifndef ZSVRCONTROLDIALOG_H | ||
#define ZSVRCONTROLDIALOG_H | ||
|
||
#include <QDialog> | ||
#include <QTreeWidgetItem> | ||
#include "zsvr/zerocoin.h" | ||
|
||
class CZerocoinMint; | ||
class WalletModel; | ||
|
||
namespace Ui { | ||
class ZSvrControlDialog; | ||
} | ||
|
||
class CZSvrControlWidgetItem : public QTreeWidgetItem | ||
{ | ||
public: | ||
explicit CZSvrControlWidgetItem(QTreeWidget *parent, int type = Type) : QTreeWidgetItem(parent, type) {} | ||
explicit CZSvrControlWidgetItem(int type = Type) : QTreeWidgetItem(type) {} | ||
explicit CZSvrControlWidgetItem(QTreeWidgetItem *parent, int type = Type) : QTreeWidgetItem(parent, type) {} | ||
|
||
bool operator<(const QTreeWidgetItem &other) const; | ||
}; | ||
|
||
class ZSvrControlDialog : public QDialog | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
explicit ZSvrControlDialog(QWidget *parent); | ||
~ZSvrControlDialog(); | ||
|
||
void setModel(WalletModel* model); | ||
|
||
static std::set<std::string> setSelectedMints; | ||
static std::set<CMintMeta> setMints; | ||
static std::vector<CMintMeta> GetSelectedMints(); | ||
|
||
private: | ||
Ui::ZSvrControlDialog *ui; | ||
WalletModel* model; | ||
|
||
void updateList(); | ||
void updateLabels(); | ||
|
||
enum { | ||
COLUMN_CHECKBOX, | ||
COLUMN_DENOMINATION, | ||
COLUMN_PUBCOIN, | ||
COLUMN_VERSION, | ||
COLUMN_CONFIRMATIONS, | ||
COLUMN_ISSPENDABLE | ||
}; | ||
friend class CZSvrControlWidgetItem; | ||
|
||
private Q_SLOTS: | ||
void updateSelection(QTreeWidgetItem* item, int column); | ||
void ButtonAllClicked(); | ||
}; | ||
|
||
#endif // ZPIVCONTROLDIALOG_H |