Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/qt/bitcoin.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<file alias="bitcoin">res/icons/bitcoin.png</file>
<file alias="address-book">res/icons/address-book.png</file>
<file alias="send">res/icons/send.png</file>
<file alias="coins">res/icons/coins.png</file>
<file alias="connect_0">res/icons/connect0.png</file>
<file alias="connect_1">res/icons/connect1.png</file>
<file alias="connect_2">res/icons/connect2.png</file>
Expand Down
66 changes: 66 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ void BitcoinGUI::createActions()
historyAction->setShortcut(QKeySequence(QStringLiteral("Alt+4")));
tabGroup->addAction(historyAction);

showCoinsAction = new QAction(platformStyle->SingleColorIcon(":/icons/coins"), tr("&Coins"), this);
showCoinsAction->setStatusTip(tr("View wallet coins (UTXOs)"));
showCoinsAction->setToolTip(showCoinsAction->statusTip());
showCoinsAction->setCheckable(true);
showCoinsAction->setShortcut(QKeySequence(QStringLiteral("Alt+5")));
tabGroup->addAction(showCoinsAction);

#ifdef ENABLE_WALLET
// These showNormalIfMinimized are needed because Send Coins and Receive Coins
// can be triggered from the tray menu, and need to show the GUI to be useful.
Expand All @@ -288,6 +295,7 @@ void BitcoinGUI::createActions()
connect(receiveCoinsAction, &QAction::triggered, this, &BitcoinGUI::gotoReceiveCoinsPage);
connect(historyAction, &QAction::triggered, [this]{ showNormalIfMinimized(); });
connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage);
connect(showCoinsAction, &QAction::triggered, this, &BitcoinGUI::showCoins);
#endif // ENABLE_WALLET

quitAction = new QAction(tr("E&xit"), this);
Expand Down Expand Up @@ -601,8 +609,12 @@ void BitcoinGUI::createToolBars()
toolbar->addAction(sendCoinsAction);
toolbar->addAction(receiveCoinsAction);
toolbar->addAction(historyAction);
toolbar->addAction(showCoinsAction);
overviewAction->setChecked(true);

showCoinsAction->setVisible(false);
showCoinsAction->setEnabled(false);

#ifdef ENABLE_WALLET
QWidget *spacer = new QWidget();
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Expand Down Expand Up @@ -676,6 +688,14 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
}

m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());

// watch for runtime changes and hide/show the coins tab accordingly
updateCoinsTabVisibility();
if (optionsModel) {
connect(optionsModel, &OptionsModel::coinControlFeaturesChanged, this, [this](bool) {
updateCoinsTabVisibility();
});
}
} else {
// Shutdown requested, disable menus
if (trayIconMenu)
Expand Down Expand Up @@ -822,6 +842,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
sendCoinsAction->setEnabled(enabled);
receiveCoinsAction->setEnabled(enabled);
historyAction->setEnabled(enabled);
showCoinsAction->setEnabled(enabled);
encryptWalletAction->setEnabled(enabled);
backupWalletAction->setEnabled(enabled);
changePassphraseAction->setEnabled(enabled);
Expand All @@ -832,6 +853,8 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
openAction->setEnabled(enabled);
m_close_wallet_action->setEnabled(enabled);
m_close_all_wallets_action->setEnabled(enabled);
m_wallet_actions_enabled = enabled;
updateCoinsTabVisibility();
}

void BitcoinGUI::createTrayIcon()
Expand Down Expand Up @@ -1293,6 +1316,7 @@ void BitcoinGUI::changeEvent(QEvent *e)
sendCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/send")));
receiveCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/receiving_addresses")));
historyAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/history")));
showCoinsAction->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/coins")));
}

QMainWindow::changeEvent(e);
Expand Down Expand Up @@ -1468,6 +1492,24 @@ void BitcoinGUI::updateWalletStatus()
}
#endif // ENABLE_WALLET

#ifdef ENABLE_WALLET
void BitcoinGUI::showCoins()
{
if (!(clientModel && clientModel->getOptionsModel() && clientModel->getOptionsModel()->getCoinControlFeatures())) {
if (overviewAction) overviewAction->setChecked(true);
// if user disables coin control features while this view is active, switch to overview
if (walletFrame) walletFrame->gotoOverviewPage();
return;
}

if (showCoinsAction) showCoinsAction->setChecked(true);
if (!walletFrame) return;
if (WalletView* wv = walletFrame->currentWalletView()) {
wv->gotoCoinsPage();
}
}
#endif // ENABLE_WALLET

void BitcoinGUI::updateProxyIcon()
{
std::string ip_port;
Expand Down Expand Up @@ -1680,3 +1722,27 @@ void UnitDisplayStatusBarControl::onMenuSelection(QAction* action)
optionsModel->setDisplayUnit(action->data());
}
}

void BitcoinGUI::updateCoinsTabVisibility()
{
if (!showCoinsAction) return;

bool coin_control_enabled = false;
if (clientModel && clientModel->getOptionsModel()) {
coin_control_enabled = clientModel->getOptionsModel()->getCoinControlFeatures();
}

// Visible only when wallet is compiled/enabled and coin control is enabled
const bool visible = enableWallet && coin_control_enabled;
showCoinsAction->setVisible(visible);

// Enabled only when visible and wallet actions are globally enabled
showCoinsAction->setEnabled(visible && m_wallet_actions_enabled);

#ifdef ENABLE_WALLET
// If the Coins tab is active but we turn it off, switch to Overview page
if (!visible && showCoinsAction->isChecked()) {
gotoOverviewPage();
}
#endif
}
9 changes: 9 additions & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class BitcoinGUI : public QMainWindow
QAction* historyAction = nullptr;
QAction* quitAction = nullptr;
QAction* sendCoinsAction = nullptr;
QAction* showCoinsAction = nullptr;
QAction* usedSendingAddressesAction = nullptr;
QAction* usedReceivingAddressesAction = nullptr;
QAction* signMessageAction = nullptr;
Expand Down Expand Up @@ -213,6 +214,12 @@ class BitcoinGUI : public QMainWindow
/** Open the OptionsDialog on the specified tab index */
void openOptionsDialogWithTab(OptionsDialog::Tab tab);

// Track whether wallet actions are globally enabled
bool m_wallet_actions_enabled{false};

/** Update the visibility and enabled state of the Coins tab/action based on options. */
void updateCoinsTabVisibility();

Q_SIGNALS:
void quitRequested();
/** Signal raised when a URI was entered or dragged to the GUI */
Expand Down Expand Up @@ -283,6 +290,8 @@ public Q_SLOTS:
void gotoReceiveCoinsPage();
/** Switch to send coins page */
void gotoSendCoinsPage(QString addr = "");
/** Switch to show coins page*/
void showCoins();

/** Show Sign/Verify Message dialog and switch to sign message tab */
void gotoSignMessageTab(QString addr = "");
Expand Down
41 changes: 38 additions & 3 deletions src/qt/coincontroldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,39 @@ void CoinControlDialog::changeEvent(QEvent* e)
QDialog::changeEvent(e);
}

void CoinControlDialog::setViewOnly(bool view_only)
{
m_view_only = view_only;

ui->pushButtonSelectAll->setVisible(true);
ui->treeWidget->setColumnHidden(COLUMN_CHECKBOX, false);
ui->frame->setVisible(true);

ui->radioListMode->setVisible(true);
ui->radioTreeMode->setVisible(true);
ui->radioListMode->setEnabled(true);
ui->radioTreeMode->setEnabled(true);

ui->labelCoinControlQuantity->setVisible(true);
ui->labelCoinControlAmount->setVisible(true);
ui->labelCoinControlFee->setVisible(!view_only);
ui->labelCoinControlAfterFee->setVisible(!view_only);
ui->labelCoinControlBytes->setVisible(!view_only);
ui->labelCoinControlChange->setVisible(!view_only);

ui->labelCoinControlQuantityText->setVisible(true);
ui->labelCoinControlAmountText->setVisible(true);
ui->labelCoinControlFeeText->setVisible(!view_only);
ui->labelCoinControlAfterFeeText->setVisible(!view_only);
ui->labelCoinControlBytesText->setVisible(!view_only);
ui->labelCoinControlChangeText->setVisible(!view_only);

if (view_only) {
lockAction->setVisible(false);
unlockAction->setVisible(false);
}
}

void CoinControlDialog::updateView()
{
if (!model || !model->getOptionsModel() || !model->getAddressTableModel())
Expand All @@ -560,8 +593,9 @@ void CoinControlDialog::updateView()
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::ItemIsAutoTristate;

QFlags<Qt::ItemFlag> flgCheckbox = (Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
QFlags<Qt::ItemFlag> flgTristate = (Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate);

BitcoinUnit nDisplayUnit = model->getOptionsModel()->getDisplayUnit();

Expand All @@ -578,6 +612,7 @@ void CoinControlDialog::updateView()
itemWalletAddress = new CCoinControlWidgetItem(ui->treeWidget);

itemWalletAddress->setFlags(flgTristate);

itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);

// label
Expand All @@ -599,7 +634,7 @@ void CoinControlDialog::updateView()
if (treeMode) itemOutput = new CCoinControlWidgetItem(itemWalletAddress);
else itemOutput = new CCoinControlWidgetItem(ui->treeWidget);
itemOutput->setFlags(flgCheckbox);
itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked);
itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);

// address
CTxDestination outputAddress;
Expand Down
4 changes: 4 additions & 0 deletions src/qt/coincontroldialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class CoinControlDialog : public QDialog
static QList<CAmount> payAmounts;
static bool fSubtractFeeFromAmount;

void setViewOnly(bool view_only);

protected:
void changeEvent(QEvent* e) override;

Expand All @@ -71,6 +73,8 @@ class CoinControlDialog : public QDialog

const PlatformStyle *platformStyle;

bool m_view_only{false};

void sortView(int, Qt::SortOrder);
void updateView();

Expand Down
Binary file added src/qt/res/icons/coins.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/qt/res/src/coins.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions src/qt/walletview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#include <qt/transactiontablemodel.h>
#include <qt/transactionview.h>
#include <qt/walletmodel.h>
#include <qt/coincontroldialog.h>
#include <wallet/coincontrol.h>
#include <QDialogButtonBox>

#include <interfaces/node.h>
#include <node/interface_ui.h>
Expand Down Expand Up @@ -69,10 +72,26 @@ WalletView::WalletView(WalletModel* wallet_model, const PlatformStyle* _platform
usedReceivingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
usedReceivingAddressesPage->setModel(walletModel->getAddressTableModel());

// Create embedded Coins (UTXOs) page
coinsPage = new QWidget(this);
{
QVBoxLayout* coinsLayout = new QVBoxLayout(coinsPage);
coinsWidget = new CoinControlDialog(coinsPageCoinControl, walletModel, platformStyle, coinsPage);
coinsWidget->setViewOnly(true);
// Make it behave as a plain widget in-page
coinsWidget->setWindowFlags(Qt::Widget);
// Hide the dialog button box when embedded
if (auto bb = coinsWidget->findChild<QDialogButtonBox*>("buttonBox")) {
bb->setVisible(false);
}
coinsLayout->addWidget(coinsWidget);
}

addWidget(overviewPage);
addWidget(transactionsPage);
addWidget(receiveCoinsPage);
addWidget(sendCoinsPage);
addWidget(coinsPage);

connect(overviewPage, &OverviewPage::transactionClicked, this, &WalletView::transactionClicked);
// Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
Expand Down Expand Up @@ -166,6 +185,17 @@ void WalletView::gotoSendCoinsPage(QString addr)
sendCoinsPage->setAddress(addr);
}

void WalletView::gotoCoinsPage()
{
setCurrentWidget(coinsPage);
}

void WalletView::showCoinsDialog()
{
if (!walletModel) return;
gotoCoinsPage();
}

void WalletView::gotoSignMessageTab(QString addr)
{
// calls show() in showTab_SM()
Expand Down
11 changes: 11 additions & 0 deletions src/qt/walletview.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include <QStackedWidget>

#include <wallet/coincontrol.h>

class ClientModel;
class OverviewPage;
class PlatformStyle;
Expand All @@ -19,6 +21,7 @@ class SendCoinsRecipient;
class TransactionView;
class WalletModel;
class AddressBookPage;
class CoinControlDialog;

QT_BEGIN_NAMESPACE
class QModelIndex;
Expand Down Expand Up @@ -65,6 +68,10 @@ class WalletView : public QStackedWidget
AddressBookPage *usedSendingAddressesPage;
AddressBookPage *usedReceivingAddressesPage;

QWidget* coinsPage{nullptr};
CoinControlDialog* coinsWidget{nullptr};
wallet::CCoinControl coinsPageCoinControl;

TransactionView *transactionView;

QProgressDialog* progressDialog{nullptr};
Expand All @@ -79,6 +86,10 @@ public Q_SLOTS:
void gotoReceiveCoinsPage();
/** Switch to send coins page */
void gotoSendCoinsPage(QString addr = "");
/** Switch to embedded Coins (UTXOs) page */
void gotoCoinsPage();
/** Switch to show coins page*/
void showCoinsDialog();

/** Show Sign/Verify Message dialog and switch to sign message tab */
void gotoSignMessageTab(QString addr = "");
Expand Down