Merge #12610: Multiwallet for the GUI

779c5f984 Qt: hide RPCConsole wallet selector when no wallets are present (Jonas Schnelli)
dc6f150f3 Qt: show wallet name in request dlg in case of multiwallet (Jonas Schnelli)
4826ca4b8 Qt: show wallet name in send confirmation dlg in case of multiwallet (Jonas Schnelli)
cfa4133ce GUI: RPCConsole: Log wallet changes (Luke Dashjr)
b6d04fc7c Qt: Get wallet name from WalletModel rather than passing it around (Luke Dashjr)
12d8d2681 Qt: When multiple wallets are used, include in notifications the name (Jonas Schnelli)
d1ec34a76 Qt: QComboBox::setVisible doesn't work in toolbars, so defer adding it at all until needed (Luke Dashjr)
d49cc70e6 Qt: Add wallet selector to debug console (Jonas Schnelli)
d558f44c5 Bugfix: RPC: Add missing UnregisterHTTPHandler for /wallet/ (Luke Dashjr)
85d531971 Qt: Ensure UI updates only come from the currently selected walletView (Luke Dashjr)
e449f9a9e Qt: Add a combobox to toolbar to select from multiple wallets (Luke Dashjr)
3dba3c3ac Qt: Load all wallets into WalletModels (Luke Dashjr)

Pull request description:

  This is an overhaul of #11383 (plus some additions).
  It avoids unnecessary coupling of httpserver/jsonrpc and the wallet as well as it avoids pointer pure passing (and pointer deletion) of `CWallet` (plus other minor design changes).

  Additionally it adds the wallet name to the sendconfirmation and request dialog (in case multiwallet is active)

Tree-SHA512: 3d06e18badbc5d1821e488bf1dae463bb0be544cf11b2b618e025812bfdd13c5f39604bb93b4c705313930e7dc4e66f4848b9469ba14871bade58e7a027246a1
This commit is contained in:
Jonas Schnelli 2018-03-26 18:50:54 +07:00 committed by pasta
parent 83726d286e
commit 2af7ce84fb
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
17 changed files with 216 additions and 71 deletions

View File

@ -258,6 +258,9 @@ void StopHTTPRPC()
{
LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n");
UnregisterHTTPHandler("/", true);
#ifdef ENABLE_WALLET
UnregisterHTTPHandler("/wallet/", false);
#endif
if (httpRPCTimerInterface) {
RPCUnsetTimerInterface(httpRPCTimerInterface.get());
httpRPCTimerInterface.reset();

View File

@ -23,6 +23,7 @@
#include <privatesend/privatesend-client.h>
#include <qt/walletframe.h>
#include <qt/walletmodel.h>
#include <qt/walletview.h>
#endif // ENABLE_WALLET
#ifdef Q_OS_MAC
@ -41,6 +42,7 @@
#include <QAction>
#include <QApplication>
#include <QButtonGroup>
#include <QComboBox>
#include <QDateTime>
#include <QDesktopWidget>
#include <QDragEnterEvent>
@ -70,10 +72,6 @@ const std::string BitcoinGUI::DEFAULT_UIPLATFORM =
#endif
;
/** Display name for default wallet name. Uses tilde to avoid name
* collisions in the future with additional wallets */
const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *networkStyle, QWidget *parent) :
QMainWindow(parent),
enableWallet(false),
@ -88,6 +86,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle *
progressBar(0),
progressDialog(0),
appMenuBar(0),
appToolBar(0),
overviewAction(0),
historyAction(0),
masternodeAction(0),
@ -588,6 +587,7 @@ void BitcoinGUI::createToolBars()
if(walletFrame)
{
QToolBar *toolbar = new QToolBar(tr("Tabs toolbar"));
appToolBar = toolbar;
toolbar->setContextMenuPolicy(Qt::PreventContextMenu);
toolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
toolbar->setToolButtonStyle(Qt::ToolButtonTextOnly);
@ -612,6 +612,15 @@ void BitcoinGUI::createToolBars()
toolbar->setMovable(false); // remove unused icon in upper left corner
overviewAction->setChecked(true);
#ifdef ENABLE_WALLET
QWidget *spacer = new QWidget();
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
toolbar->addWidget(spacer);
m_wallet_selector = new QComboBox();
connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&)));
#endif
QLabel *logoLabel = new QLabel();
logoLabel->setObjectName("lblToolbarLogo");
logoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
@ -729,12 +738,22 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
}
#ifdef ENABLE_WALLET
bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
bool BitcoinGUI::addWallet(WalletModel *walletModel)
{
if(!walletFrame)
return false;
const QString name = walletModel->getWalletName();
setWalletActionsEnabled(true);
return walletFrame->addWallet(name, walletModel);
m_wallet_selector->addItem(name);
if (m_wallet_selector->count() == 2) {
m_wallet_selector_label = new QLabel();
m_wallet_selector_label->setText(tr("Wallet:") + " ");
m_wallet_selector_label->setBuddy(m_wallet_selector);
appToolBar->addWidget(m_wallet_selector_label);
appToolBar->addWidget(m_wallet_selector);
}
rpcConsole->addWallet(walletModel);
return walletFrame->addWallet(walletModel);
}
bool BitcoinGUI::setCurrentWallet(const QString& name)
@ -1317,7 +1336,7 @@ void BitcoinGUI::showEvent(QShowEvent *event)
}
#ifdef ENABLE_WALLET
void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName)
{
IncomingTransactionMessage itx = {
date, unit, amount, type, address, label
@ -1386,8 +1405,11 @@ void BitcoinGUI::showIncomingTransactions()
for (auto& itx : txs) {
// On new transaction, make an info balloon
QString msg = tr("Date: %1\n").arg(itx.date) +
tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(itx.unit, itx.amount, true)) +
tr("Type: %1\n").arg(itx.type);
tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(itx.unit, itx.amount, true));
if (WalletModel::isMultiwallet() && !walletName.isEmpty()) {
msg += tr("Wallet: %1\n").arg(walletName);
}
msg += tr("Type: %1\n").arg(itx.type);
if (!itx.label.isEmpty())
msg += tr("Label: %1\n").arg(itx.label);
else if (!itx.address.isEmpty())
@ -1496,6 +1518,20 @@ void BitcoinGUI::setEncryptionStatus(int status)
break;
}
}
void BitcoinGUI::updateWalletStatus()
{
if (!walletFrame) {
return;
}
WalletView * const walletView = walletFrame->currentWalletView();
if (!walletView) {
return;
}
WalletModel * const walletModel = walletView->getWalletModel();
setEncryptionStatus(walletModel->getEncryptionStatus());
setHDStatus(walletModel->hdEnabled());
}
#endif // ENABLE_WALLET
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)

View File

@ -38,6 +38,7 @@ class ModalOverlay;
QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
class QProgressBar;
class QProgressDialog;
class QToolButton;
@ -52,7 +53,6 @@ class BitcoinGUI : public QMainWindow
Q_OBJECT
public:
static const QString DEFAULT_WALLET;
static const std::string DEFAULT_UIPLATFORM;
explicit BitcoinGUI(const PlatformStyle *platformStyle, const NetworkStyle *networkStyle, QWidget *parent = 0);
@ -68,8 +68,7 @@ public:
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
functionality.
*/
bool addWallet(const QString& name, WalletModel *walletModel);
bool setCurrentWallet(const QString& name);
bool addWallet(WalletModel *walletModel);
void removeAllWallets();
#endif // ENABLE_WALLET
bool enableWallet;
@ -96,6 +95,7 @@ private:
QProgressDialog *progressDialog;
QMenuBar *appMenuBar;
QToolBar *appToolBar;
QToolButton *overviewAction;
QToolButton *historyAction;
QToolButton *masternodeAction;
@ -130,6 +130,9 @@ private:
QAction *showHelpMessageAction;
QAction *showPrivateSendHelpAction;
QLabel *m_wallet_selector_label;
QComboBox *m_wallet_selector;
QSystemTrayIcon *trayIcon;
QMenu *trayIconMenu;
QMenu *dockIconMenu;
@ -212,22 +215,29 @@ public Q_SLOTS:
void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr);
#ifdef ENABLE_WALLET
/** Set the hd-enabled status as shown in the UI.
@param[in] status current hd enabled status
@see WalletModel::EncryptionStatus
*/
void setHDStatus(int hdEnabled);
bool setCurrentWallet(const QString& name);
/** Set the UI status indicators based on the currently selected wallet.
*/
void updateWalletStatus();
private:
/** Set the encryption status as shown in the UI.
@param[in] status current encryption status
@see WalletModel::EncryptionStatus
*/
void setEncryptionStatus(int status);
/** Set the hd-enabled status as shown in the UI.
@param[in] status current hd enabled status
@see WalletModel::EncryptionStatus
*/
void setHDStatus(int hdEnabled);
public Q_SLOTS:
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
/** Show incoming transaction notification for new transactions. */
void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label);
void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
void showIncomingTransactions();
#endif // ENABLE_WALLET

View File

@ -232,7 +232,7 @@ private:
QTimer *pollShutdownTimer;
#ifdef ENABLE_WALLET
PaymentServer* paymentServer;
WalletModel *walletModel;
std::vector<WalletModel*> m_wallet_models;
#endif
int returnValue;
const PlatformStyle *platformStyle;
@ -334,7 +334,7 @@ BitcoinApplication::BitcoinApplication(int &argc, char **argv):
pollShutdownTimer(0),
#ifdef ENABLE_WALLET
paymentServer(0),
walletModel(0),
m_wallet_models(),
#endif
returnValue(0)
{
@ -461,8 +461,10 @@ void BitcoinApplication::requestShutdown()
#ifdef ENABLE_WALLET
window->removeAllWallets();
delete walletModel;
walletModel = 0;
for (WalletModel *walletModel : m_wallet_models) {
delete walletModel;
}
m_wallet_models.clear();
#endif
delete clientModel;
clientModel = 0;
@ -491,16 +493,20 @@ void BitcoinApplication::initializeResult(bool success)
window->setClientModel(clientModel);
#ifdef ENABLE_WALLET
// TODO: Expose secondary wallets
if (HasWallets())
{
walletModel = new WalletModel(platformStyle, GetWallets()[0], optionsModel);
bool fFirstWallet = true;
for (CWallet* pwallet : GetWallets()) {
WalletModel * const walletModel = new WalletModel(platformStyle, pwallet, optionsModel);
window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel);
window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET);
window->addWallet(walletModel);
if (fFirstWallet) {
window->setCurrentWallet(walletModel->getWalletName());
fFirstWallet = false;
}
connect(walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)),
paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray)));
m_wallet_models.push_back(walletModel);
}
#endif

View File

@ -494,6 +494,22 @@
<property name="spacing">
<number>4</number>
</property>
<item>
<widget class="QLabel" name="WalletSelectorLabel">
<property name="text">
<string>Wallet: </string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="WalletSelector">
<item>
<property name="text">
<string>(none)</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

View File

@ -143,7 +143,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
ui->reqAmount->value(), ui->reqMessage->text());
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModel(model->getOptionsModel());
dialog->setModel(model);
dialog->setInfo(info);
dialog->show();
clear();
@ -156,7 +156,7 @@ void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &
{
const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
dialog->setModel(model->getOptionsModel());
dialog->setModel(model);
dialog->setInfo(submodel->entry(index.row()).recipient);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();

View File

@ -107,12 +107,12 @@ ReceiveRequestDialog::~ReceiveRequestDialog()
delete ui;
}
void ReceiveRequestDialog::setModel(OptionsModel *_model)
void ReceiveRequestDialog::setModel(WalletModel *_model)
{
this->model = _model;
if (_model)
connect(_model, SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
connect(_model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(update()));
// update the display unit if necessary
update();
@ -143,11 +143,14 @@ void ReceiveRequestDialog::update()
uri + "\">" + GUIUtil::HtmlEscape(uri) + "</a><br>";
html += "<b>"+tr("Address")+"</b>: " + GUIUtil::HtmlEscape(info.address) + "<br>";
if(info.amount)
html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getDisplayUnit(), info.amount) + "<br>";
html += "<b>"+tr("Amount")+"</b>: " + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), info.amount) + "<br>";
if(!info.label.isEmpty())
html += "<b>"+tr("Label")+"</b>: " + GUIUtil::HtmlEscape(info.label) + "<br>";
if(!info.message.isEmpty())
html += "<b>"+tr("Message")+"</b>: " + GUIUtil::HtmlEscape(info.message) + "<br>";
if(model->isMultiwallet()) {
html += "<b>"+tr("Wallet")+"</b>: " + GUIUtil::HtmlEscape(model->getWalletName()) + "<br>";
}
ui->outUri->setText(html);
#ifdef USE_QRCODE

View File

@ -12,8 +12,6 @@
#include <QLabel>
#include <QPainter>
class OptionsModel;
namespace Ui {
class ReceiveRequestDialog;
}
@ -53,7 +51,7 @@ public:
explicit ReceiveRequestDialog(QWidget *parent = 0);
~ReceiveRequestDialog();
void setModel(OptionsModel *model);
void setModel(WalletModel *model);
void setInfo(const SendCoinsRecipient &info);
private Q_SLOTS:
@ -64,7 +62,7 @@ private Q_SLOTS:
private:
Ui::ReceiveRequestDialog *ui;
OptionsModel *model;
WalletModel *model;
SendCoinsRecipient info;
};

View File

@ -13,6 +13,7 @@
#include <qt/bantablemodel.h>
#include <qt/clientmodel.h>
#include <qt/platformstyle.h>
#include <qt/walletmodel.h>
#include <chainparams.h>
#include <netbase.h>
#include <rpc/server.h>
@ -91,7 +92,7 @@ class RPCExecutor : public QObject
Q_OBJECT
public Q_SLOTS:
void request(const QString &command);
void request(const QString &command, const QString &walletID);
Q_SIGNALS:
void reply(int category, const QString &command);
@ -152,7 +153,7 @@ public:
* @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data
*/
bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut)
bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID)
{
std::vector< std::vector<std::string> > stack;
stack.push_back(std::vector<std::string>());
@ -310,10 +311,8 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
req.strMethod = stack.back()[0];
#ifdef ENABLE_WALLET
// TODO: Move this logic to WalletModel
if (HasWallets()) {
// in Qt, use always the wallet with index 0 when running with multiple wallets
QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(GetWallets()[0]->GetName()));
if (walletID && !walletID->empty()) {
QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID));
req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
}
#endif
@ -392,7 +391,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
}
}
void RPCExecutor::request(const QString &command)
void RPCExecutor::request(const QString &command, const QString &walletID)
{
try
{
@ -423,7 +422,8 @@ void RPCExecutor::request(const QString &command)
" example: getblock(getblockhash(0),true)[tx][0]\n\n")));
return;
}
if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand))
std::string wallet_id = walletID.toStdString();
if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand, nullptr, &wallet_id))
{
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
return;
@ -498,6 +498,10 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller()));
connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
// disable the wallet selector by default
ui->WalletSelector->setVisible(false);
ui->WalletSelectorLabel->setVisible(false);
// Wallet Repair Buttons
// connect(ui->btn_salvagewallet, SIGNAL(clicked()), this, SLOT(walletSalvage()));
// Disable salvage option in GUI, it's way too powerful and can lead to funds loss
@ -735,6 +739,23 @@ void RPCConsole::setClientModel(ClientModel *model)
}
}
#ifdef ENABLE_WALLET
void RPCConsole::addWallet(WalletModel * const walletModel)
{
const QString name = walletModel->getWalletName();
// use name for text and internal data object (to allow to move to a wallet id later)
ui->WalletSelector->addItem(name, name);
if (ui->WalletSelector->count() == 2 && !isVisible()) {
// First wallet added, set to default so long as the window isn't presently visible (and potentially in use)
ui->WalletSelector->setCurrentIndex(1);
}
if (ui->WalletSelector->count() > 2) {
ui->WalletSelector->setVisible(true);
ui->WalletSelectorLabel->setVisible(true);
}
}
#endif
static QString categoryClass(int category)
{
switch(category)
@ -1016,8 +1037,25 @@ void RPCConsole::on_lineEdit_returnPressed()
cmdBeforeBrowsing = QString();
QString walletID;
#ifdef ENABLE_WALLET
const int wallet_index = ui->WalletSelector->currentIndex();
if (wallet_index > 0) {
walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>();
}
if (m_last_wallet_id != walletID) {
if (walletID.isEmpty()) {
message(CMD_REQUEST, tr("Executing command without any wallet"));
} else {
message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID));
}
m_last_wallet_id = walletID;
}
#endif
message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
Q_EMIT cmdRequest(cmd);
Q_EMIT cmdRequest(cmd, walletID);
cmd = QString::fromStdString(strFilteredCmd);
@ -1065,7 +1103,7 @@ void RPCConsole::startExecutor()
// Replies from executor object must go to this object
connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
// Requests from this object must go to executor
connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
connect(this, SIGNAL(cmdRequest(QString, QString)), executor, SLOT(request(QString, QString)));
// On stopExecutor signal
// - quit the Qt event loop in the execution thread

View File

@ -19,6 +19,7 @@
class ClientModel;
class PlatformStyle;
class RPCTimerInterface;
class WalletModel;
namespace Ui {
class RPCConsole;
@ -38,12 +39,13 @@ public:
explicit RPCConsole(const PlatformStyle *platformStyle, QWidget *parent);
~RPCConsole();
static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr);
static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr) {
return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut);
static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr);
static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) {
return RPCParseCommandLine(strResult, strCommand, true, pstrFilteredOut, walletID);
}
void setClientModel(ClientModel *model);
void addWallet(WalletModel * const walletModel);
enum MessageClass {
MC_ERROR,
@ -94,7 +96,7 @@ public Q_SLOTS:
void fontBigger();
void fontSmaller();
void setFontSize(int newSize);
/** Wallet repair options */
void walletSalvage();
void walletRescan();
@ -102,7 +104,7 @@ public Q_SLOTS:
void walletZaptxes2();
void walletUpgrade();
void walletReindex();
/** Append the message to the message widget */
void message(int category, const QString &message, bool html = false);
/** Set number of connections shown in the UI */
@ -139,7 +141,7 @@ public Q_SLOTS:
Q_SIGNALS:
// For RPC command executor
void stopExecutor();
void cmdRequest(const QString &command);
void cmdRequest(const QString &command, const QString &walletID);
/** Get restart command-line parameters and handle restart */
void handleRestart(QStringList args);
@ -175,6 +177,7 @@ private:
int consoleFontSize;
QCompleter *autoCompleter;
QThread thread;
QString m_last_wallet_id;
/** Update UI with latest network info from model. */
void updateNetworkState();

View File

@ -331,10 +331,12 @@ void SendCoinsDialog::send(QList<SendCoinsRecipient> recipients)
QStringList formatted;
for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients())
{
// generate bold amount string
// generate bold amount string with wallet name in case of multiwallet
QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
if (model->isMultiwallet()) {
amount.append(" <u>"+tr("from wallet %1").arg(GUIUtil::HtmlEscape(model->getWalletName()))+"</u> ");
}
amount.append("</b> ");
// generate monospace address string
QString address = "<span style='font-family: monospace;'>" + rcp.address;
address.append("</span>");

View File

@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/walletframe.h>
#include <qt/walletmodel.h>
#include <qt/bitcoingui.h>
#include <qt/walletview.h>
@ -39,10 +40,16 @@ void WalletFrame::setClientModel(ClientModel *_clientModel)
this->clientModel = _clientModel;
}
bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
bool WalletFrame::addWallet(WalletModel *walletModel)
{
if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
if (!gui || !clientModel || !walletModel) {
return false;
}
const QString name = walletModel->getWalletName();
if (mapWalletViews.count(name) > 0) {
return false;
}
WalletView *walletView = new WalletView(platformStyle, this);
walletView->setBitcoinGUI(gui);

View File

@ -36,7 +36,7 @@ public:
void setClientModel(ClientModel *clientModel);
bool addWallet(const QString& name, WalletModel *walletModel);
bool addWallet(WalletModel *walletModel);
bool setCurrentWallet(const QString& name);
bool removeWallet(const QString &name);
void removeAllWallets();
@ -59,6 +59,7 @@ private:
const PlatformStyle *platformStyle;
public:
WalletView *currentWalletView();
public Q_SLOTS:

View File

@ -138,8 +138,9 @@ void WalletModel::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
if(cachedEncryptionStatus != newEncryptionStatus)
Q_EMIT encryptionStatusChanged(newEncryptionStatus);
if(cachedEncryptionStatus != newEncryptionStatus) {
Q_EMIT encryptionStatusChanged();
}
}
void WalletModel::pollBalanceChanged()
@ -808,3 +809,18 @@ int WalletModel::getDefaultConfirmTarget() const
{
return nTxConfirmTarget;
}
QString WalletModel::getWalletName() const
{
LOCK(wallet->cs_wallet);
QString walletName = QString::fromStdString(wallet->GetName());
if (walletName.endsWith(".dat")) {
walletName.truncate(walletName.size() - 4);
}
return walletName;
}
bool WalletModel::isMultiwallet()
{
return gArgs.GetArgs("-wallet").size() > 1;
}

View File

@ -133,6 +133,8 @@ public:
TransactionTableModel *getTransactionTableModel();
RecentRequestsTableModel *getRecentRequestsTableModel();
CWallet *getWallet() const { return wallet; };
CAmount getBalance(const CCoinControl *coinControl = nullptr) const;
CAmount getUnconfirmedBalance() const;
CAmount getImmatureBalance() const;
@ -232,6 +234,9 @@ public:
int getRealOutpointPrivateSendRounds(const COutPoint& outpoint) const;
QString getWalletName() const;
static bool isMultiwallet();
private:
CWallet *wallet;
bool fHaveWatchOnly;
@ -270,7 +275,7 @@ Q_SIGNALS:
const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance);
// Encryption status of wallet changed
void encryptionStatusChanged(int status);
void encryptionStatusChanged();
// Signal emitted when wallet needs to be unlocked
// It is valid behaviour for listeners to keep the wallet locked after this signal;

View File

@ -134,13 +134,13 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
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)));
connect(this, SIGNAL(encryptionStatusChanged()), gui, SLOT(updateWalletStatus()));
// Pass through transaction notifications
connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString)));
connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString,QString)));
// Connect HD enabled state signal
connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int)));
connect(this, SIGNAL(hdEnabledStatusChanged()), gui, SLOT(updateWalletStatus()));
}
}
@ -178,11 +178,11 @@ void WalletView::setWalletModel(WalletModel *_walletModel)
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)));
connect(_walletModel, SIGNAL(encryptionStatusChanged()), this, SIGNAL(encryptionStatusChanged()));
updateEncryptionStatus();
// update HD status
Q_EMIT hdEnabledStatusChanged(_walletModel->hdEnabled());
Q_EMIT hdEnabledStatusChanged();
// Balloon pop-up for new transaction
connect(_walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
@ -222,7 +222,7 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int
QString address = ttm->data(index, TransactionTableModel::AddressRole).toString();
QString label = ttm->data(index, TransactionTableModel::LabelRole).toString();
Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label);
Q_EMIT incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label, walletModel->getWalletName());
}
void WalletView::gotoOverviewPage()
@ -303,7 +303,7 @@ void WalletView::showOutOfSyncWarning(bool fShow)
void WalletView::updateEncryptionStatus()
{
Q_EMIT encryptionStatusChanged(walletModel->getEncryptionStatus());
Q_EMIT encryptionStatusChanged();
}
void WalletView::encryptWallet(bool status)

View File

@ -46,6 +46,7 @@ public:
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
*/
void setClientModel(ClientModel *clientModel);
WalletModel *getWalletModel() { return walletModel; }
/** Set the wallet model.
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
functionality.
@ -132,11 +133,11 @@ Q_SIGNALS:
/** Fired when a message should be reported to the user */
void message(const QString &title, const QString &message, unsigned int style);
/** Encryption status of wallet changed */
void encryptionStatusChanged(int status);
void encryptionStatusChanged();
/** HD-Enabled status of wallet changed (only possible during startup) */
void hdEnabledStatusChanged(int hdEnabled);
void hdEnabledStatusChanged();
/** Notify that a new transaction appeared */
void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label);
void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label, const QString& walletName);
/** Notify that the out of sync warning icon has been pressed */
void outOfSyncWarningClicked();
};