ui: Support wallets unloaded dynamically

This commit is contained in:
João Barbosa 2018-06-05 11:17:28 +01:00
parent 9f9b50d5fe
commit 0ee77b2077
9 changed files with 80 additions and 8 deletions

View file

@ -429,6 +429,10 @@ public:
bool hdEnabled() override { return m_wallet.IsHDEnabled(); } bool hdEnabled() override { return m_wallet.IsHDEnabled(); }
OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; } OutputType getDefaultAddressType() override { return m_wallet.m_default_address_type; }
OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; } OutputType getDefaultChangeType() override { return m_wallet.m_default_change_type; }
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
{
return MakeHandler(m_wallet.NotifyUnload.connect(fn));
}
std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
{ {
return MakeHandler(m_wallet.ShowProgress.connect(fn)); return MakeHandler(m_wallet.ShowProgress.connect(fn));

View file

@ -242,6 +242,10 @@ public:
// Get default change type. // Get default change type.
virtual OutputType getDefaultChangeType() = 0; virtual OutputType getDefaultChangeType() = 0;
//! Register handler for unload message.
using UnloadFn = std::function<void()>;
virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
//! Register handler for show progress messages. //! Register handler for show progress messages.
using ShowProgressFn = std::function<void(const std::string& title, int progress)>; using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0; virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;

View file

@ -238,6 +238,7 @@ public Q_SLOTS:
/// Handle runaway exceptions. Shows a message box with the problem and quits the program. /// Handle runaway exceptions. Shows a message box with the problem and quits the program.
void handleRunawayException(const QString &message); void handleRunawayException(const QString &message);
void addWallet(WalletModel* walletModel); void addWallet(WalletModel* walletModel);
void removeWallet();
Q_SIGNALS: Q_SIGNALS:
void requestedInitialize(); void requestedInitialize();
@ -467,11 +468,22 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)), connect(walletModel, SIGNAL(coinsSent(WalletModel*, SendCoinsRecipient, QByteArray)),
paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray))); paymentServer, SLOT(fetchPaymentACK(WalletModel*, const SendCoinsRecipient&, QByteArray)));
connect(walletModel, SIGNAL(unload()), this, SLOT(removeWallet()));
m_wallet_models.push_back(walletModel); m_wallet_models.push_back(walletModel);
#endif #endif
} }
void BitcoinApplication::removeWallet()
{
#ifdef ENABLE_WALLET
WalletModel* walletModel = static_cast<WalletModel*>(sender());
m_wallet_models.erase(std::find(m_wallet_models.begin(), m_wallet_models.end(), walletModel));
window->removeWallet(walletModel);
walletModel->deleteLater();
#endif
}
void BitcoinApplication::initializeResult(bool success) void BitcoinApplication::initializeResult(bool success)
{ {
qDebug() << __func__ << ": Initialization result: " << success; qDebug() << __func__ << ": Initialization result: " << success;
@ -491,8 +503,10 @@ void BitcoinApplication::initializeResult(bool success)
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) { m_handler_load_wallet = m_node.handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, WalletModel* wallet_model = new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel, nullptr);
Q_ARG(WalletModel*, new WalletModel(std::move(wallet), m_node, platformStyle, optionsModel))); // Fix wallet model thread affinity.
wallet_model->moveToThread(thread());
QMetaObject::invokeMethod(this, "addWallet", Qt::QueuedConnection, Q_ARG(WalletModel*, wallet_model));
}); });
for (auto& wallet : m_node.getWallets()) { for (auto& wallet : m_node.getWallets()) {

View file

@ -120,6 +120,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
modalOverlay(0), modalOverlay(0),
prevBlocks(0), prevBlocks(0),
spinnerFrame(0), spinnerFrame(0),
m_wallet_selector_label(nullptr),
platformStyle(_platformStyle) platformStyle(_platformStyle)
{ {
QSettings settings; QSettings settings;
@ -477,6 +478,16 @@ void BitcoinGUI::createToolBars()
m_wallet_selector = new QComboBox(); m_wallet_selector = new QComboBox();
connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int))); connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
m_wallet_selector_label = new QLabel();
m_wallet_selector_label->setText(tr("Wallet:") + " ");
m_wallet_selector_label->setBuddy(m_wallet_selector);
m_wallet_selector_label_action = appToolBar->addWidget(m_wallet_selector_label);
m_wallet_selector_action = appToolBar->addWidget(m_wallet_selector);
m_wallet_selector_label_action->setVisible(false);
m_wallet_selector_action->setVisible(false);
#endif #endif
} }
} }
@ -556,16 +567,29 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
setWalletActionsEnabled(true); setWalletActionsEnabled(true);
m_wallet_selector->addItem(display_name, name); m_wallet_selector->addItem(display_name, name);
if (m_wallet_selector->count() == 2) { if (m_wallet_selector->count() == 2) {
m_wallet_selector_label = new QLabel(); m_wallet_selector_label_action->setVisible(true);
m_wallet_selector_label->setText(tr("Wallet:") + " "); m_wallet_selector_action->setVisible(true);
m_wallet_selector_label->setBuddy(m_wallet_selector);
appToolBar->addWidget(m_wallet_selector_label);
appToolBar->addWidget(m_wallet_selector);
} }
rpcConsole->addWallet(walletModel); rpcConsole->addWallet(walletModel);
return walletFrame->addWallet(walletModel); return walletFrame->addWallet(walletModel);
} }
bool BitcoinGUI::removeWallet(WalletModel* walletModel)
{
if (!walletFrame) return false;
QString name = walletModel->getWalletName();
int index = m_wallet_selector->findData(name);
m_wallet_selector->removeItem(index);
if (m_wallet_selector->count() == 0) {
setWalletActionsEnabled(false);
} else if (m_wallet_selector->count() == 1) {
m_wallet_selector_label_action->setVisible(false);
m_wallet_selector_action->setVisible(false);
}
rpcConsole->removeWallet(walletModel);
return walletFrame->removeWallet(name);
}
bool BitcoinGUI::setCurrentWallet(const QString& name) bool BitcoinGUI::setCurrentWallet(const QString& name)
{ {
if(!walletFrame) if(!walletFrame)

View file

@ -70,6 +70,7 @@ public:
functionality. functionality.
*/ */
bool addWallet(WalletModel *walletModel); bool addWallet(WalletModel *walletModel);
bool removeWallet(WalletModel* walletModel);
void removeAllWallets(); void removeAllWallets();
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
bool enableWallet; bool enableWallet;
@ -122,8 +123,10 @@ private:
QAction *openRPCConsoleAction; QAction *openRPCConsoleAction;
QAction *openAction; QAction *openAction;
QAction *showHelpMessageAction; QAction *showHelpMessageAction;
QAction *m_wallet_selector_label_action = nullptr;
QAction *m_wallet_selector_action = nullptr;
QLabel *m_wallet_selector_label; QLabel *m_wallet_selector_label = nullptr;
QComboBox *m_wallet_selector; QComboBox *m_wallet_selector;
QSystemTrayIcon *trayIcon; QSystemTrayIcon *trayIcon;

View file

@ -713,6 +713,16 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
ui->WalletSelectorLabel->setVisible(true); ui->WalletSelectorLabel->setVisible(true);
} }
} }
void RPCConsole::removeWallet(WalletModel * const walletModel)
{
const QString name = walletModel->getWalletName();
ui->WalletSelector->removeItem(ui->WalletSelector->findData(name));
if (ui->WalletSelector->count() == 2) {
ui->WalletSelector->setVisible(false);
ui->WalletSelectorLabel->setVisible(false);
}
}
#endif #endif
static QString categoryClass(int category) static QString categoryClass(int category)

View file

@ -48,6 +48,7 @@ public:
void setClientModel(ClientModel *model); void setClientModel(ClientModel *model);
void addWallet(WalletModel * const walletModel); void addWallet(WalletModel * const walletModel);
void removeWallet(WalletModel* const walletModel);
enum MessageClass { enum MessageClass {
MC_ERROR, MC_ERROR,

View file

@ -364,6 +364,12 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
} }
// Handlers for core signals // Handlers for core signals
static void NotifyUnload(WalletModel* walletModel)
{
qDebug() << "NotifyUnload";
QMetaObject::invokeMethod(walletModel, "unload", Qt::QueuedConnection);
}
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel) static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel)
{ {
qDebug() << "NotifyKeyStoreStatusChanged"; qDebug() << "NotifyKeyStoreStatusChanged";
@ -411,6 +417,7 @@ static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly
void WalletModel::subscribeToCoreSignals() void WalletModel::subscribeToCoreSignals()
{ {
// Connect signals to wallet // Connect signals to wallet
m_handler_unload = m_wallet->handleUnload(boost::bind(&NotifyUnload, this));
m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this)); m_handler_status_changed = m_wallet->handleStatusChanged(boost::bind(&NotifyKeyStoreStatusChanged, this));
m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5)); m_handler_address_book_changed = m_wallet->handleAddressBookChanged(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2)); m_handler_transaction_changed = m_wallet->handleTransactionChanged(boost::bind(NotifyTransactionChanged, this, _1, _2));
@ -421,6 +428,7 @@ void WalletModel::subscribeToCoreSignals()
void WalletModel::unsubscribeFromCoreSignals() void WalletModel::unsubscribeFromCoreSignals()
{ {
// Disconnect signals from wallet // Disconnect signals from wallet
m_handler_unload->disconnect();
m_handler_status_changed->disconnect(); m_handler_status_changed->disconnect();
m_handler_address_book_changed->disconnect(); m_handler_address_book_changed->disconnect();
m_handler_transaction_changed->disconnect(); m_handler_transaction_changed->disconnect();

View file

@ -208,6 +208,7 @@ public:
AddressTableModel* getAddressTableModel() const { return addressTableModel; } AddressTableModel* getAddressTableModel() const { return addressTableModel; }
private: private:
std::unique_ptr<interfaces::Wallet> m_wallet; std::unique_ptr<interfaces::Wallet> m_wallet;
std::unique_ptr<interfaces::Handler> m_handler_unload;
std::unique_ptr<interfaces::Handler> m_handler_status_changed; std::unique_ptr<interfaces::Handler> m_handler_status_changed;
std::unique_ptr<interfaces::Handler> m_handler_address_book_changed; std::unique_ptr<interfaces::Handler> m_handler_address_book_changed;
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed; std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
@ -261,6 +262,9 @@ Q_SIGNALS:
// Watch-only address added // Watch-only address added
void notifyWatchonlyChanged(bool fHaveWatchonly); void notifyWatchonlyChanged(bool fHaveWatchonly);
// Signal that wallet is about to be removed
void unload();
public Q_SLOTS: public Q_SLOTS:
/* Wallet status might have changed */ /* Wallet status might have changed */
void updateStatus(); void updateStatus();