Files
agrarian/src/qt/walletview.cpp
T
2026-04-30 06:38:51 +00:00

466 lines
16 KiB
C++

// Copyright (c) 2011-2015 The Bitcoin developers
// Copyright (c) 2016-2019 The PIVX developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "walletview.h"
#include "addressbookpage.h"
#include "bip38tooldialog.h"
#include "bitcoingui.h"
#include "blockexplorer.h"
#include "clientmodel.h"
#include "governancepage.h"
#include "guiutil.h"
#include "masternodeconfig.h"
#include "multisenddialog.h"
#include "multisigdialog.h"
#include "optionsmodel.h"
#include "overviewpage.h"
#include "receivecoinsdialog.h"
#include "privacydialog.h"
#include "sendcoinsdialog.h"
#include "signverifymessagedialog.h"
#include "transactiontablemodel.h"
#include "transactionview.h"
#include "walletmodel.h"
#include "guiinterface.h"
#include <QAction>
#include <QActionGroup>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QSettings>
#include <QVBoxLayout>
WalletView::WalletView(QWidget* parent) : QStackedWidget(parent),
clientModel(0),
walletModel(0)
{
// Create tabs
overviewPage = new OverviewPage();
explorerWindow = new BlockExplorer(this);
transactionsPage = new QWidget(this);
// Create Header with the same names as the other forms to be CSS-Id compatible
QFrame *frame_Header = new QFrame(transactionsPage);
frame_Header->setObjectName(QStringLiteral("frame_Header"));
QVBoxLayout* verticalLayout_8 = new QVBoxLayout(frame_Header);
verticalLayout_8->setObjectName(QStringLiteral("verticalLayout_8"));
verticalLayout_8->setContentsMargins(0, 0, 0, 0);
QHBoxLayout* horizontalLayout_Header = new QHBoxLayout();
horizontalLayout_Header->setObjectName(QStringLiteral("horizontalLayout_Header"));
QLabel* labelOverviewHeaderLeft = new QLabel(frame_Header);
labelOverviewHeaderLeft->setObjectName(QStringLiteral("labelOverviewHeaderLeft"));
labelOverviewHeaderLeft->setMinimumSize(QSize(464, 60));
labelOverviewHeaderLeft->setMaximumSize(QSize(16777215, 60));
labelOverviewHeaderLeft->setText(tr("HISTORY"));
QFont fontHeaderLeft;
fontHeaderLeft.setPointSize(20);
fontHeaderLeft.setBold(true);
fontHeaderLeft.setWeight(QFont::Bold);
labelOverviewHeaderLeft->setFont(fontHeaderLeft);
horizontalLayout_Header->addWidget(labelOverviewHeaderLeft);
QSpacerItem* horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_Header->addItem(horizontalSpacer_3);
QLabel* labelOverviewHeaderRight = new QLabel(frame_Header);
labelOverviewHeaderRight->setObjectName(QStringLiteral("labelOverviewHeaderRight"));
labelOverviewHeaderRight->setMinimumSize(QSize(464, 60));
labelOverviewHeaderRight->setMaximumSize(QSize(16777215, 60));
labelOverviewHeaderRight->setText(QString());
QFont fontHeaderRight;
fontHeaderRight.setPointSize(14);
labelOverviewHeaderRight->setFont(fontHeaderRight);
labelOverviewHeaderRight->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
horizontalLayout_Header->addWidget(labelOverviewHeaderRight);
horizontalLayout_Header->setStretch(0, 1);
horizontalLayout_Header->setStretch(2, 1);
verticalLayout_8->addLayout(horizontalLayout_Header);
QVBoxLayout* vbox = new QVBoxLayout();
QHBoxLayout* hbox_buttons = new QHBoxLayout();
vbox->addWidget(frame_Header);
transactionView = new TransactionView(this);
vbox->addWidget(transactionView);
QPushButton* exportButton = new QPushButton(tr("&Export"), this);
exportButton->setToolTip(tr("Export the data in the current tab to a file"));
#ifndef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
exportButton->setIcon(QIcon(":/icons/export"));
#endif
hbox_buttons->addStretch();
// Sum of selected transactions
QLabel* transactionSumLabel = new QLabel(); // Label
transactionSumLabel->setObjectName("transactionSumLabel"); // Label ID as CSS-reference
transactionSumLabel->setText(tr("Selected amount:"));
hbox_buttons->addWidget(transactionSumLabel);
transactionSum = new QLabel(); // Amount
transactionSum->setObjectName("transactionSum"); // Label ID as CSS-reference
transactionSum->setMinimumSize(200, 8);
transactionSum->setTextInteractionFlags(Qt::TextSelectableByMouse);
hbox_buttons->addWidget(transactionSum);
hbox_buttons->addWidget(exportButton);
vbox->addLayout(hbox_buttons);
transactionsPage->setLayout(vbox);
privacyPage = new PrivacyDialog();
governancePage = new GovernancePage();
receiveCoinsPage = new ReceiveCoinsDialog();
sendCoinsPage = new SendCoinsDialog();
addWidget(overviewPage);
addWidget(transactionsPage);
addWidget(privacyPage);
addWidget(governancePage);
addWidget(receiveCoinsPage);
addWidget(sendCoinsPage);
addWidget(explorerWindow);
QSettings settings;
if (settings.value("fShowMasternodesTab").toBool()) {
masternodeListPage = new MasternodeList();
addWidget(masternodeListPage);
}
// Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
// Double-clicking on a transaction on the transaction history page shows details
connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
// Update wallet with sum of selected transactions
connect(transactionView, SIGNAL(trxAmount(QString)), this, SLOT(trxAmount(QString)));
// Clicking on "Export" allows to export the transaction list
connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));
// Pass through messages from sendCoinsPage
connect(sendCoinsPage, SIGNAL(message(QString, QString, unsigned int)), this, SIGNAL(message(QString, QString, unsigned int)));
// Pass through messages from transactionView
connect(transactionView, SIGNAL(message(QString, QString, unsigned int)), this, SIGNAL(message(QString, QString, unsigned int)));
}
WalletView::~WalletView()
{
}
void WalletView::setBitcoinGUI(BitcoinGUI* gui)
{
if (gui) {
// Clicking on a transaction on the overview page simply sends you to transaction history page
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));
// Receive and report messages
connect(this, SIGNAL(message(QString, QString, unsigned int)), gui, SLOT(message(QString, QString, unsigned int)));
// Pass through encryption status changed signals
connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));
// Pass through transaction notifications
connect(this, SIGNAL(incomingTransaction(QString, int, CAmount, QString, QString)), gui, SLOT(incomingTransaction(QString, int, CAmount, QString, QString)));
}
}
void WalletView::setClientModel(ClientModel* clientModel)
{
this->clientModel = clientModel;
overviewPage->setClientModel(clientModel);
sendCoinsPage->setClientModel(clientModel);
QSettings settings;
if (settings.value("fShowMasternodesTab").toBool()) {
masternodeListPage->setClientModel(clientModel);
}
governancePage->setClientModel(clientModel);
}
void WalletView::setWalletModel(WalletModel* walletModel)
{
this->walletModel = walletModel;
// Put transaction list in tabs
transactionView->setModel(walletModel);
overviewPage->setWalletModel(walletModel);
QSettings settings;
if (settings.value("fShowMasternodesTab").toBool()) {
masternodeListPage->setWalletModel(walletModel);
}
privacyPage->setModel(walletModel);
receiveCoinsPage->setModel(walletModel);
sendCoinsPage->setModel(walletModel);
governancePage->setWalletModel(walletModel);
if (walletModel) {
// Receive and pass through messages from wallet model
connect(walletModel, SIGNAL(message(QString, QString, unsigned int)), this, SIGNAL(message(QString, QString, unsigned int)));
// Handle changes in encryption status
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
updateEncryptionStatus();
// Balloon pop-up for new transaction
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex, int, int)),
this, SLOT(processNewTransaction(QModelIndex, int, int)));
// Ask for passphrase if needed
connect(walletModel, SIGNAL(requireUnlock(AskPassphraseDialog::Context)), this, SLOT(unlockWallet(AskPassphraseDialog::Context)));
// Show progress dialog
connect(walletModel, SIGNAL(showProgress(QString, int)), this, SLOT(showProgress(QString, int)));
}
}
void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
// Prevent balloon-spam when initial block download is in progress
if (!walletModel || !clientModel || clientModel->inInitialBlockDownload())
return;
TransactionTableModel* ttm = walletModel->getTransactionTableModel();
if (!ttm || ttm->processingQueuedTransactions())
return;
QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString();
emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
}
void WalletView::gotoOverviewPage()
{
setCurrentWidget(overviewPage);
// Refresh UI-elements in case coins were locked/unlocked in CoinControl
walletModel->emitBalanceChanged();
}
void WalletView::gotoHistoryPage()
{
setCurrentWidget(transactionsPage);
}
void WalletView::gotoGovernancePage()
{
setCurrentWidget(governancePage);
}
void WalletView::gotoBlockExplorerPage()
{
setCurrentWidget(explorerWindow);
}
void WalletView::gotoMasternodePage()
{
QSettings settings;
if (settings.value("fShowMasternodesTab").toBool()) {
setCurrentWidget(masternodeListPage);
}
}
void WalletView::gotoReceiveCoinsPage()
{
setCurrentWidget(receiveCoinsPage);
}
void WalletView::gotoPrivacyPage()
{
setCurrentWidget(privacyPage);
// Refresh UI-elements in case coins were locked/unlocked in CoinControl
walletModel->emitBalanceChanged();
}
void WalletView::gotoSendCoinsPage(QString addr)
{
setCurrentWidget(sendCoinsPage);
if (!addr.isEmpty())
sendCoinsPage->setAddress(addr);
}
void WalletView::gotoSignMessageTab(QString addr)
{
// calls show() in showTab_SM()
SignVerifyMessageDialog* signVerifyMessageDialog = new SignVerifyMessageDialog(this);
signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
signVerifyMessageDialog->setModel(walletModel);
signVerifyMessageDialog->showTab_SM(true);
if (!addr.isEmpty())
signVerifyMessageDialog->setAddress_SM(addr);
}
void WalletView::gotoVerifyMessageTab(QString addr)
{
// calls show() in showTab_VM()
SignVerifyMessageDialog* signVerifyMessageDialog = new SignVerifyMessageDialog(this);
signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
signVerifyMessageDialog->setModel(walletModel);
signVerifyMessageDialog->showTab_VM(true);
if (!addr.isEmpty())
signVerifyMessageDialog->setAddress_VM(addr);
}
void WalletView::gotoBip38Tool()
{
Bip38ToolDialog* bip38ToolDialog = new Bip38ToolDialog(this);
//bip38ToolDialog->setAttribute(Qt::WA_DeleteOnClose);
bip38ToolDialog->setModel(walletModel);
bip38ToolDialog->showTab_ENC(true);
}
void WalletView::gotoMultiSendDialog()
{
MultiSendDialog* multiSendDialog = new MultiSendDialog(this);
multiSendDialog->setModel(walletModel);
multiSendDialog->show();
}
void WalletView::gotoMultisigDialog(int index)
{
MultisigDialog* multisig = new MultisigDialog(this);
multisig->setModel(walletModel);
multisig->showTab(index);
}
bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
return sendCoinsPage->handlePaymentRequest(recipient);
}
void WalletView::showOutOfSyncWarning(bool fShow)
{
overviewPage->showOutOfSyncWarning(fShow);
privacyPage->showOutOfSyncWarning(fShow);
}
void WalletView::updateEncryptionStatus()
{
emit encryptionStatusChanged(walletModel->getEncryptionStatus());
}
void WalletView::encryptWallet(bool status)
{
if (!walletModel)
return;
AskPassphraseDialog dlg(status ? AskPassphraseDialog::Mode::Encrypt : AskPassphraseDialog::Mode::Decrypt, this,
walletModel, AskPassphraseDialog::Context::Encrypt);
dlg.exec();
updateEncryptionStatus();
}
void WalletView::backupWallet()
{
QString filename = GUIUtil::getSaveFileName(this,
tr("Backup Wallet"), QString(),
tr("Wallet Data (*.dat)"), NULL);
if (filename.isEmpty())
return;
walletModel->backupWallet(filename);
}
void WalletView::changePassphrase()
{
AskPassphraseDialog dlg(AskPassphraseDialog::Mode::ChangePass, this, walletModel, AskPassphraseDialog::Context::ChangePass);
dlg.exec();
}
void WalletView::unlockWallet(AskPassphraseDialog::Context context)
{
if (!walletModel)
return;
// Unlock wallet when requested by wallet model
if (walletModel->getEncryptionStatus() == WalletModel::Locked || walletModel->getEncryptionStatus() == WalletModel::UnlockedForAnonymizationOnly) {
AskPassphraseDialog dlg(AskPassphraseDialog::Mode::UnlockAnonymize, this, walletModel, context);
dlg.exec();
}
}
void WalletView::lockWallet()
{
if (!walletModel)
return;
walletModel->setWalletLocked(true);
}
void WalletView::toggleLockWallet()
{
if (!walletModel)
return;
WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus();
// Unlock the wallet when requested
if (encStatus == walletModel->Locked) {
AskPassphraseDialog dlg(AskPassphraseDialog::Mode::UnlockAnonymize, this, walletModel, AskPassphraseDialog::Context::ToggleLock);
dlg.exec();
}
else if (encStatus == walletModel->Unlocked || encStatus == walletModel->UnlockedForAnonymizationOnly) {
walletModel->setWalletLocked(true);
}
}
void WalletView::usedSendingAddresses()
{
if (!walletModel)
return;
AddressBookPage* dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->setModel(walletModel->getAddressTableModel());
dlg->show();
}
void WalletView::usedReceivingAddresses()
{
if (!walletModel)
return;
AddressBookPage* dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->setModel(walletModel->getAddressTableModel());
dlg->show();
}
void WalletView::showProgress(const QString& title, int nProgress)
{
if (nProgress == 0) {
progressDialog = new QProgressDialog(title, "", 0, 100);
progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setMinimumDuration(0);
progressDialog->setCancelButton(0);
progressDialog->setAutoClose(false);
progressDialog->setValue(0);
} else if (nProgress == 100) {
if (progressDialog) {
progressDialog->close();
progressDialog->deleteLater();
}
} else if (progressDialog)
progressDialog->setValue(nProgress);
}
/** Update wallet with the sum of the selected transactions */
void WalletView::trxAmount(QString amount)
{
transactionSum->setText(amount);
}