Skip to content

Commit 0ee77b2

Browse files
committed
ui: Support wallets unloaded dynamically
1 parent 9f9b50d commit 0ee77b2

File tree

9 files changed

+80
-8
lines changed

9 files changed

+80
-8
lines changed

src/interfaces/wallet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,10 @@ class WalletImpl : public Wallet
429429
bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
430430
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
431431
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
432+
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
433+
{
434+
return MakeHandler(m_wallet.NotifyUnload.connect(fn));
435+
}
432436
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
433437
{
434438
return MakeHandler(m_wallet.ShowProgress.connect(fn));

src/interfaces/wallet.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ class Wallet
242242
// Get default change type.
243243
virtual OutputType getDefaultChangeType() = 0;
244244

245+
//! Register handler for unload message.
246+
using UnloadFn = std::function<void()>;
247+
virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
248+
245249
//! Register handler for show progress messages.
246250
using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
247251
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;

src/qt/bitcoin.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ public Q_SLOTS:
238238
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
239239
void handleRunawayException(const QString &message);
240240
void addWallet(WalletModel* walletModel);
241+
void removeWallet();
241242

242243
Q_SIGNALS:
243244
void requestedInitialize();
@@ -467,11 +468,22 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
467468

468469
connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)),
469470
paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray)));
471+
connect(walletModel, SIGNAL(unload()), this, SLOT(removeWallet()));
470472

471473
m_wallet_models.push_back(walletModel);
472474
#endif
473475
}
474476

477+
void BitcoinApplication::removeWallet()
478+
{
479+
#ifdef ENABLE_WALLET
480+
WalletModel* walletModel = static_cast<WalletModel*>(sender());
481+
m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel));
482+
window->removeWallet(walletModel);
483+
walletModel->deleteLater();
484+
#endif
485+
}
486+
475487
void BitcoinApplication::initializeResult(bool success)
476488
{
477489
qDebug() << __func__ << ": Initialization result: " << success;
@@ -491,8 +503,10 @@ void BitcoinApplication::initializeResult(bool success)
491503

492504
#ifdef ENABLE_WALLET
493505
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
494-
QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection,
495-
Q_ARG(WalletModel*, new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel)));
506+
WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr);
507+
// Fix wallet model thread affinity.
508+
wallet_model->moveToThread(thread());
509+
QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
496510
});
497511

498512
for (auto& wallet : m_node.getWallets()) {

src/qt/bitcoingui.cpp

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
120120
modalOverlay(0),
121121
prevBlocks(0),
122122
spinnerFrame(0),
123+
m_wallet_selector_label(nullptr),
123124
platformStyle(_platformStyle)
124125
{
125126
QSettings settings;
@@ -477,6 +478,16 @@ void BitcoinGUI::createToolBars()
477478

478479
m_wallet_selector = new QComboBox();
479480
connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
481+
482+
m_wallet_selector_label = new QLabel();
483+
m_wallet_selector_label->setText(tr("Wallet:") + " ");
484+
m_wallet_selector_label->setBuddy(m_wallet_selector);
485+
486+
m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
487+
m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
488+
489+
m_wallet_selector_label_action->setVisible(false);
490+
m_wallet_selector_action->setVisible(false);
480491
#endif
481492
}
482493
}
@@ -556,16 +567,29 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
556567
setWalletActionsEnabled(true);
557568
m_wallet_selector->addItem(display_name, name);
558569
if (m_wallet_selector->count() == 2) {
559-
m_wallet_selector_label = new QLabel();
560-
m_wallet_selector_label->setText(tr("Wallet:") + " ");
561-
m_wallet_selector_label->setBuddy(m_wallet_selector);
562-
appToolBar->addWidget(m_wallet_selector_label);
563-
appToolBar->addWidget(m_wallet_selector);
570+
m_wallet_selector_label_action->setVisible(true);
571+
m_wallet_selector_action->setVisible(true);
564572
}
565573
rpcConsole->addWallet(walletModel);
566574
return walletFrame->addWallet(walletModel);
567575
}
568576

577+
bool BitcoinGUI::removeWallet(WalletModel* walletModel)
578+
{
579+
if (!walletFrame) return false;
580+
QString name = walletModel->getWalletName();
581+
int index = m_wallet_selector->findData(name);
582+
m_wallet_selector->removeItem(index);
583+
if (m_wallet_selector->count() == 0) {
584+
setWalletActionsEnabled(false);
585+
} else if (m_wallet_selector->count() == 1) {
586+
m_wallet_selector_label_action->setVisible(false);
587+
m_wallet_selector_action->setVisible(false);
588+
}
589+
rpcConsole->removeWallet(walletModel);
590+
return walletFrame->removeWallet(name);
591+
}
592+
569593
bool BitcoinGUI::setCurrentWallet(const QString& name)
570594
{
571595
if(!walletFrame)

src/qt/bitcoingui.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class BitcoinGUI : public QMainWindow
7070
functionality.
7171
*/
7272
bool addWallet(WalletModel *walletModel);
73+
bool removeWallet(WalletModel* walletModel);
7374
void removeAllWallets();
7475
#endif // ENABLE_WALLET
7576
bool enableWallet;
@@ -122,8 +123,10 @@ class BitcoinGUI : public QMainWindow
122123
QAction *openRPCConsoleAction;
123124
QAction *openAction;
124125
QAction *showHelpMessageAction;
126+
QAction *m_wallet_selector_label_action = nullptr;
127+
QAction *m_wallet_selector_action = nullptr;
125128

126-
QLabel *m_wallet_selector_label;
129+
QLabel *m_wallet_selector_label = nullptr;
127130
QComboBox *m_wallet_selector;
128131

129132
QSystemTrayIcon *trayIcon;

src/qt/rpcconsole.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,16 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
713713
ui->WalletSelectorLabel->setVisible(true);
714714
}
715715
}
716+
717+
void RPCConsole::removeWallet(WalletModel * const walletModel)
718+
{
719+
const QString name = walletModel->getWalletName();
720+
ui->WalletSelector->removeItem(ui->WalletSelector->findData(name));
721+
if (ui->WalletSelector->count() == 2) {
722+
ui->WalletSelector->setVisible(false);
723+
ui->WalletSelectorLabel->setVisible(false);
724+
}
725+
}
716726
#endif
717727

718728
static QString categoryClass(int category)

src/qt/rpcconsole.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class RPCConsole: public QWidget
4848

4949
void setClientModel(ClientModel *model);
5050
void addWallet(WalletModel * const walletModel);
51+
void removeWallet(WalletModel* const walletModel);
5152

5253
enum MessageClass {
5354
MC_ERROR,

src/qt/walletmodel.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
364364
}
365365

366366
// Handlers for core signals
367+
static void NotifyUnload(WalletModel* walletModel)
368+
{
369+
qDebug() << "NotifyUnload";
370+
QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection);
371+
}
372+
367373
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
368374
{
369375
qDebug() << "NotifyKeyStoreStatusChanged";
@@ -411,6 +417,7 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
411417
void WalletModel::subscribeToCoreSignals()
412418
{
413419
// Connect signals to wallet
420+
m_handler_unload = m_wallet->handleUnload(boost::bind(&NotifyUnload, this));
414421
m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
415422
m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
416423
m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
@@ -421,6 +428,7 @@ void WalletModel::subscribeToCoreSignals()
421428
void WalletModel::unsubscribeFromCoreSignals()
422429
{
423430
// Disconnect signals from wallet
431+
m_handler_unload->disconnect();
424432
m_handler_status_changed->disconnect();
425433
m_handler_address_book_changed->disconnect();
426434
m_handler_transaction_changed->disconnect();

src/qt/walletmodel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ class WalletModel : public QObject
208208
AddressTableModel* getAddressTableModel() const { return addressTableModel; }
209209
private:
210210
std::unique_ptr<interfaces::Wallet> m_wallet;
211+
std::unique_ptr<interfaces::Handler> m_handler_unload;
211212
std::unique_ptr<interfaces::Handler> m_handler_status_changed;
212213
std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
213214
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
@@ -261,6 +262,9 @@ class WalletModel : public QObject
261262
// Watch-only address added
262263
void notifyWatchonlyChanged(bool fHaveWatchonly);
263264

265+
// Signal that wallet is about to be removed
266+
void unload();
267+
264268
public Q_SLOTS:
265269
/* Wallet status might have changed */
266270
void updateStatus();

0 commit comments

Comments
 (0)