diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index fed373e551c..c3a68966bd2 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -3,6 +3,7 @@
res/icons/bitcoin.png
res/icons/address-book.png
res/icons/send.png
+ res/icons/coins.png
res/icons/connect0.png
res/icons/connect1.png
res/icons/connect2.png
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 9413356b412..a65d7709bde 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -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.
@@ -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);
@@ -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);
@@ -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)
@@ -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);
@@ -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()
@@ -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);
@@ -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;
@@ -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
+}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 32fb7488fb0..2d3711fef46 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -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;
@@ -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 */
@@ -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 = "");
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index febf1ee82fa..50867b80fba 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -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())
@@ -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 flgCheckbox = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
- QFlags flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate;
+
+ QFlags flgCheckbox = (Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
+ QFlags flgTristate = (Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate);
BitcoinUnit nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
@@ -578,6 +612,7 @@ void CoinControlDialog::updateView()
itemWalletAddress = new CCoinControlWidgetItem(ui->treeWidget);
itemWalletAddress->setFlags(flgTristate);
+
itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
// label
@@ -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;
diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h
index 5fc2cdca9b7..8878c148fa6 100644
--- a/src/qt/coincontroldialog.h
+++ b/src/qt/coincontroldialog.h
@@ -53,6 +53,8 @@ class CoinControlDialog : public QDialog
static QList payAmounts;
static bool fSubtractFeeFromAmount;
+ void setViewOnly(bool view_only);
+
protected:
void changeEvent(QEvent* e) override;
@@ -71,6 +73,8 @@ class CoinControlDialog : public QDialog
const PlatformStyle *platformStyle;
+ bool m_view_only{false};
+
void sortView(int, Qt::SortOrder);
void updateView();
diff --git a/src/qt/res/icons/coins.png b/src/qt/res/icons/coins.png
new file mode 100644
index 00000000000..34a8f017d8f
Binary files /dev/null and b/src/qt/res/icons/coins.png differ
diff --git a/src/qt/res/src/coins.svg b/src/qt/res/src/coins.svg
new file mode 100644
index 00000000000..8835674bdd7
--- /dev/null
+++ b/src/qt/res/src/coins.svg
@@ -0,0 +1,15 @@
+
+
+
\ No newline at end of file
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 39e9dcadeed..40c8e05a1da 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -17,6 +17,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
@@ -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("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
@@ -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()
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index 475085044db..119459b24b5 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -10,6 +10,8 @@
#include
+#include
+
class ClientModel;
class OverviewPage;
class PlatformStyle;
@@ -19,6 +21,7 @@ class SendCoinsRecipient;
class TransactionView;
class WalletModel;
class AddressBookPage;
+class CoinControlDialog;
QT_BEGIN_NAMESPACE
class QModelIndex;
@@ -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};
@@ -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 = "");