Minimal architectural changes necessary to support multiple wallets in bitcoin-qt
- This commit is a minimal restructuring necessary to support multiple wallets in the UI. Please see multiwallet-qt.txt for details.
This commit is contained in:
parent
dfd71bb450
commit
67155d9299
11 changed files with 1097 additions and 226 deletions
|
@ -186,6 +186,9 @@ HEADERS += src/qt/bitcoingui.h \
|
|||
src/qt/transactionfilterproxy.h \
|
||||
src/qt/transactionview.h \
|
||||
src/qt/walletmodel.h \
|
||||
src/qt/walletview.h \
|
||||
src/qt/walletstack.h \
|
||||
src/qt/walletframe.h \
|
||||
src/bitcoinrpc.h \
|
||||
src/qt/overviewpage.h \
|
||||
src/qt/csvmodelwriter.h \
|
||||
|
@ -250,6 +253,9 @@ SOURCES += src/qt/bitcoin.cpp \
|
|||
src/qt/transactionfilterproxy.cpp \
|
||||
src/qt/transactionview.cpp \
|
||||
src/qt/walletmodel.cpp \
|
||||
src/qt/walletview.cpp \
|
||||
src/qt/walletstack.cpp \
|
||||
src/qt/walletframe.cpp \
|
||||
src/bitcoinrpc.cpp \
|
||||
src/rpcdump.cpp \
|
||||
src/rpcnet.cpp \
|
||||
|
|
53
multiwallet-qt.txt
Normal file
53
multiwallet-qt.txt
Normal file
|
@ -0,0 +1,53 @@
|
|||
Multiwallet Qt Development and Integration Strategy
|
||||
===================================================
|
||||
|
||||
In order to support loading of multiple wallets in bitcoin-qt, a few changes in the UI architecture will be needed.
|
||||
Fortunately, only four of the files in the existing project are affected by this change.
|
||||
|
||||
Three new classes have been implemented in three new .h/.cpp file pairs, with much of the functionality that was previously
|
||||
implemented in the BitcoinGUI class moved over to these new classes.
|
||||
|
||||
The two existing files most affected, by far, are bitcoingui.h and bitcoingui.cpp, as the BitcoinGUI class will require
|
||||
some major retrofitting.
|
||||
|
||||
Only requiring some minor changes is bitcoin.cpp.
|
||||
|
||||
Finally, three new headers and source files will have to be added to bitcoin-qt.pro.
|
||||
|
||||
Changes to class BitcoinGUI
|
||||
---------------------------
|
||||
The principal change to the BitcoinGUI class concerns the QStackedWidget instance called centralWidget.
|
||||
This widget owns five page views: overviewPage, transactionsPage, addressBookPage, receiveCoinsPage, and sendCoinsPage.
|
||||
|
||||
A new class called *WalletView* inheriting from QStackedWidget has been written to handle all renderings and updates of
|
||||
these page views. In addition to owning these five page views, a WalletView also has a pointer to a WalletModel instance.
|
||||
This allows the construction of multiple WalletView objects, each rendering a distinct wallet.
|
||||
|
||||
A second class called *WalletStack*, also inheriting from QStackedWidget, has been written to handle switching focus between
|
||||
different loaded wallets. In its current implementation, as a QStackedWidget, only one wallet can be viewed at a time -
|
||||
but this can be changed later.
|
||||
|
||||
A third class called *WalletFrame* inheriting from QFrame has been written as a container for embedding all wallet-related
|
||||
controls into BitcoinGUI. At present it just contains a WalletStack instance and does little more than passing on messages
|
||||
from BitcoinGUI to the WalletStack, which in turn passes them to the individual WalletViews. It is a WalletFrame instance
|
||||
that takes the place of what used to be centralWidget in BitcoinGUI. The purpose of this class is to allow future
|
||||
refinements of the wallet controls with minimal need for further modifications to BitcoinGUI, thus greatly simplifying
|
||||
merges while reducing the risk of breaking top-level stuff.
|
||||
|
||||
Changes to bitcoin.cpp
|
||||
----------------------
|
||||
bitcoin.cpp is the entry point into bitcoin-qt, and as such, will require some minor modifications to provide hooks for
|
||||
multiple wallet support. Most importantly will be the way it instantiates WalletModels and passes them to the
|
||||
singleton BitcoinGUI instance called window. Formerly, BitcoinGUI kept a pointer to a single instance of a WalletModel.
|
||||
The initial change required is very simple: rather than calling window.setWalletModel(&walletModel); we perform the
|
||||
following two steps:
|
||||
|
||||
window.addWallet("~Default", &walletModel);
|
||||
window.setCurrentWallet("~Default");
|
||||
|
||||
The string parameter is just an arbitrary name given to the default wallet. It's been prepended with a tilde to avoid name
|
||||
collisions in the future with additional wallets.
|
||||
|
||||
The shutdown call window.setWalletModel(0) has also been removed. In its place is now:
|
||||
|
||||
window.removeAllWallets();
|
|
@ -232,7 +232,8 @@ int main(int argc, char *argv[])
|
|||
WalletModel walletModel(pwalletMain, &optionsModel);
|
||||
|
||||
window.setClientModel(&clientModel);
|
||||
window.setWalletModel(&walletModel);
|
||||
window.addWallet("~Default", &walletModel);
|
||||
window.setCurrentWallet("~Default");
|
||||
|
||||
// If -min option passed, start window minimized.
|
||||
if(GetBoolArg("-min"))
|
||||
|
@ -253,7 +254,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
window.hide();
|
||||
window.setClientModel(0);
|
||||
window.setWalletModel(0);
|
||||
window.removeAllWallets();
|
||||
guiref = 0;
|
||||
}
|
||||
// Shutdown the core and its threads, but don't exit Bitcoin-Qt here
|
||||
|
|
|
@ -10,26 +10,20 @@
|
|||
#include "bitcoingui.h"
|
||||
|
||||
#include "transactiontablemodel.h"
|
||||
#include "addressbookpage.h"
|
||||
#include "sendcoinsdialog.h"
|
||||
#include "signverifymessagedialog.h"
|
||||
#include "optionsdialog.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "clientmodel.h"
|
||||
#include "walletmodel.h"
|
||||
#include "editaddressdialog.h"
|
||||
#include "walletframe.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "transactiondescdialog.h"
|
||||
#include "addresstablemodel.h"
|
||||
#include "transactionview.h"
|
||||
#include "overviewpage.h"
|
||||
#include "bitcoinunits.h"
|
||||
#include "guiconstants.h"
|
||||
#include "askpassphrasedialog.h"
|
||||
#include "notificator.h"
|
||||
#include "guiutil.h"
|
||||
#include "rpcconsole.h"
|
||||
#include "ui_interface.h"
|
||||
#include "wallet.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "macdockiconhandler.h"
|
||||
|
@ -54,13 +48,15 @@
|
|||
#include <QUrl>
|
||||
#include <QMimeData>
|
||||
#include <QStyle>
|
||||
#include <QListWidget>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
|
||||
|
||||
BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||
QMainWindow(parent),
|
||||
clientModel(0),
|
||||
walletModel(0),
|
||||
encryptWalletAction(0),
|
||||
changePassphraseAction(0),
|
||||
aboutQtAction(0),
|
||||
|
@ -93,31 +89,10 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
|||
// Create system tray icon and notification
|
||||
createTrayIcon();
|
||||
|
||||
// Create tabs
|
||||
overviewPage = new OverviewPage();
|
||||
|
||||
transactionsPage = new QWidget(this);
|
||||
QVBoxLayout *vbox = new QVBoxLayout();
|
||||
transactionView = new TransactionView(this);
|
||||
vbox->addWidget(transactionView);
|
||||
transactionsPage->setLayout(vbox);
|
||||
|
||||
addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab);
|
||||
|
||||
receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab);
|
||||
|
||||
sendCoinsPage = new SendCoinsDialog(this);
|
||||
|
||||
signVerifyMessageDialog = new SignVerifyMessageDialog(this);
|
||||
|
||||
centralWidget = new QStackedWidget(this);
|
||||
centralWidget->addWidget(overviewPage);
|
||||
centralWidget->addWidget(transactionsPage);
|
||||
centralWidget->addWidget(addressBookPage);
|
||||
centralWidget->addWidget(receiveCoinsPage);
|
||||
centralWidget->addWidget(sendCoinsPage);
|
||||
setCentralWidget(centralWidget);
|
||||
|
||||
// Create wallet frame and make it the central widget
|
||||
walletFrame = new WalletFrame(this);
|
||||
setCentralWidget(walletFrame);
|
||||
|
||||
// Create status bar
|
||||
statusBar();
|
||||
|
||||
|
@ -162,27 +137,11 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
|||
|
||||
syncIconMovie = new QMovie(":/movies/update_spinner", "mng", this);
|
||||
|
||||
// Clicking on a transaction on the overview page simply sends you to transaction history page
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage()));
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
|
||||
|
||||
// Double-clicking on a transaction on the transaction history page shows details
|
||||
connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
|
||||
|
||||
rpcConsole = new RPCConsole(this);
|
||||
connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show()));
|
||||
|
||||
// Clicking on "Send Coins" in the address book sends you to the send coins tab
|
||||
connect(addressBookPage, SIGNAL(sendCoins(QString)), this, SLOT(gotoSendCoinsPage(QString)));
|
||||
// Clicking on "Verify Message" in the address book opens the verify message tab in the Sign/Verify Message dialog
|
||||
connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString)));
|
||||
// Clicking on "Sign Message" in the receive coins page opens the sign message tab in the Sign/Verify Message dialog
|
||||
connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString)));
|
||||
|
||||
// Install event filter to be able to catch status tip events (QEvent::StatusTip)
|
||||
this->installEventFilter(this);
|
||||
|
||||
gotoOverviewPage();
|
||||
}
|
||||
|
||||
BitcoinGUI::~BitcoinGUI()
|
||||
|
@ -243,7 +202,7 @@ void BitcoinGUI::createActions()
|
|||
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
|
||||
connect(addressBookAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
|
||||
connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
|
||||
|
||||
|
||||
quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this);
|
||||
quitAction->setStatusTip(tr("Quit application"));
|
||||
quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
|
||||
|
@ -377,39 +336,23 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
|
|||
// Receive and report messages from network/worker thread
|
||||
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
||||
|
||||
overviewPage->setClientModel(clientModel);
|
||||
rpcConsole->setClientModel(clientModel);
|
||||
addressBookPage->setOptionsModel(clientModel->getOptionsModel());
|
||||
receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel());
|
||||
walletFrame->setClientModel(clientModel);
|
||||
}
|
||||
}
|
||||
|
||||
void BitcoinGUI::setWalletModel(WalletModel *walletModel)
|
||||
bool BitcoinGUI::addWallet(const QString& name, WalletModel *walletModel)
|
||||
{
|
||||
this->walletModel = walletModel;
|
||||
if(walletModel)
|
||||
{
|
||||
// Receive and report messages from wallet thread
|
||||
connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
|
||||
return walletFrame->addWallet(name, walletModel);
|
||||
}
|
||||
|
||||
// Put transaction list in tabs
|
||||
transactionView->setModel(walletModel);
|
||||
overviewPage->setWalletModel(walletModel);
|
||||
addressBookPage->setModel(walletModel->getAddressTableModel());
|
||||
receiveCoinsPage->setModel(walletModel->getAddressTableModel());
|
||||
sendCoinsPage->setModel(walletModel);
|
||||
signVerifyMessageDialog->setModel(walletModel);
|
||||
bool BitcoinGUI::setCurrentWallet(const QString& name)
|
||||
{
|
||||
return walletFrame->setCurrentWallet(name);
|
||||
}
|
||||
|
||||
setEncryptionStatus(walletModel->getEncryptionStatus());
|
||||
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
|
||||
|
||||
// Balloon pop-up for new transaction
|
||||
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(incomingTransaction(QModelIndex,int,int)));
|
||||
|
||||
// Ask for passphrase if needed
|
||||
connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
|
||||
}
|
||||
void BitcoinGUI::removeAllWallets()
|
||||
{
|
||||
walletFrame->removeAllWallets();
|
||||
}
|
||||
|
||||
void BitcoinGUI::createTrayIcon()
|
||||
|
@ -484,6 +427,41 @@ void BitcoinGUI::aboutClicked()
|
|||
dlg.exec();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoOverviewPage()
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoOverviewPage();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoHistoryPage()
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoHistoryPage();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoAddressBookPage()
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoAddressBookPage();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoReceiveCoinsPage()
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoReceiveCoinsPage();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoSendCoinsPage()
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoSendCoinsPage();
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoSignMessageTab(QString addr)
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoSignMessageTab(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
if (walletFrame) walletFrame->gotoSignMessageTab(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::setNumConnections(int count)
|
||||
{
|
||||
QString icon;
|
||||
|
@ -548,7 +526,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
|
|||
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
|
||||
labelBlocksIcon->setPixmap(QIcon(":/icons/synced").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
|
||||
|
||||
overviewPage->showOutOfSyncWarning(false);
|
||||
walletFrame->showOutOfSyncWarning(false);
|
||||
|
||||
progressBarLabel->setVisible(false);
|
||||
progressBar->setVisible(false);
|
||||
|
@ -583,7 +561,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks)
|
|||
syncIconMovie->jumpToNextFrame();
|
||||
prevBlocks = count;
|
||||
|
||||
overviewPage->showOutOfSyncWarning(true);
|
||||
walletFrame->showOutOfSyncWarning(true);
|
||||
|
||||
tooltip += QString("<br>");
|
||||
tooltip += tr("Last received block was generated %1 ago.").arg(timeBehindText);
|
||||
|
@ -692,104 +670,20 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
|
|||
*payFee = (retval == QMessageBox::Yes);
|
||||
}
|
||||
|
||||
void BitcoinGUI::incomingTransaction(const QModelIndex& parent, int start, int /*end*/)
|
||||
void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address)
|
||||
{
|
||||
// Prevent balloon-spam when initial block download is in progress
|
||||
if(!walletModel || !clientModel || clientModel->inInitialBlockDownload())
|
||||
return;
|
||||
|
||||
TransactionTableModel *ttm = walletModel->getTransactionTableModel();
|
||||
|
||||
QString date = ttm->index(start, TransactionTableModel::Date, parent)
|
||||
.data().toString();
|
||||
qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
|
||||
.data(Qt::EditRole).toULongLong();
|
||||
QString type = ttm->index(start, TransactionTableModel::Type, parent)
|
||||
.data().toString();
|
||||
QString address = ttm->index(start, TransactionTableModel::ToAddress, parent)
|
||||
.data().toString();
|
||||
|
||||
// On new transaction, make an info balloon
|
||||
// On new transaction, make an info balloon
|
||||
message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
|
||||
tr("Date: %1\n"
|
||||
"Amount: %2\n"
|
||||
"Type: %3\n"
|
||||
"Address: %4\n")
|
||||
.arg(date)
|
||||
.arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), amount, true))
|
||||
.arg(BitcoinUnits::formatWithUnit(unit, amount, true))
|
||||
.arg(type)
|
||||
.arg(address), CClientUIInterface::MSG_INFORMATION);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoOverviewPage()
|
||||
{
|
||||
overviewAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(overviewPage);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoHistoryPage()
|
||||
{
|
||||
historyAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(transactionsPage);
|
||||
|
||||
exportAction->setEnabled(true);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked()));
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoAddressBookPage()
|
||||
{
|
||||
addressBookAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(addressBookPage);
|
||||
|
||||
exportAction->setEnabled(true);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked()));
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoReceiveCoinsPage()
|
||||
{
|
||||
receiveCoinsAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(receiveCoinsPage);
|
||||
|
||||
exportAction->setEnabled(true);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked()));
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoSendCoinsPage(QString addr)
|
||||
{
|
||||
sendCoinsAction->setChecked(true);
|
||||
centralWidget->setCurrentWidget(sendCoinsPage);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
|
||||
if(!addr.isEmpty())
|
||||
sendCoinsPage->setAddress(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoSignMessageTab(QString addr)
|
||||
{
|
||||
// call show() in showTab_SM()
|
||||
signVerifyMessageDialog->showTab_SM(true);
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_SM(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
// call show() in showTab_VM()
|
||||
signVerifyMessageDialog->showTab_VM(true);
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_VM(addr);
|
||||
}
|
||||
|
||||
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
// Accept only URIs
|
||||
|
@ -805,13 +699,13 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
|
|||
QList<QUrl> uris = event->mimeData()->urls();
|
||||
foreach(const QUrl &uri, uris)
|
||||
{
|
||||
if (sendCoinsPage->handleURI(uri.toString()))
|
||||
if (walletFrame->handleURI(uri.toString()))
|
||||
nValidUrisFound++;
|
||||
}
|
||||
|
||||
// if valid URIs were found
|
||||
if (nValidUrisFound)
|
||||
gotoSendCoinsPage();
|
||||
walletFrame->gotoSendCoinsPage();
|
||||
else
|
||||
message(tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
|
@ -835,12 +729,7 @@ bool BitcoinGUI::eventFilter(QObject *object, QEvent *event)
|
|||
void BitcoinGUI::handleURI(QString strURI)
|
||||
{
|
||||
// URI has to be valid
|
||||
if (sendCoinsPage->handleURI(strURI))
|
||||
{
|
||||
showNormalIfMinimized();
|
||||
gotoSendCoinsPage();
|
||||
}
|
||||
else
|
||||
if (!walletFrame->handleURI(strURI))
|
||||
message(tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
|
@ -876,49 +765,22 @@ void BitcoinGUI::setEncryptionStatus(int status)
|
|||
|
||||
void BitcoinGUI::encryptWallet(bool status)
|
||||
{
|
||||
if(!walletModel)
|
||||
return;
|
||||
AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt:
|
||||
AskPassphraseDialog::Decrypt, this);
|
||||
dlg.setModel(walletModel);
|
||||
dlg.exec();
|
||||
|
||||
setEncryptionStatus(walletModel->getEncryptionStatus());
|
||||
walletFrame->encryptWallet(status);
|
||||
}
|
||||
|
||||
void BitcoinGUI::backupWallet()
|
||||
{
|
||||
QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
|
||||
if(!filename.isEmpty()) {
|
||||
if(!walletModel->backupWallet(filename)) {
|
||||
message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
else
|
||||
message(tr("Backup Successful"), tr("The wallet data was successfully saved to the new location."),
|
||||
CClientUIInterface::MSG_INFORMATION);
|
||||
}
|
||||
walletFrame->backupWallet();
|
||||
}
|
||||
|
||||
void BitcoinGUI::changePassphrase()
|
||||
{
|
||||
AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
|
||||
dlg.setModel(walletModel);
|
||||
dlg.exec();
|
||||
walletFrame->changePassphrase();
|
||||
}
|
||||
|
||||
void BitcoinGUI::unlockWallet()
|
||||
{
|
||||
if(!walletModel)
|
||||
return;
|
||||
// Unlock wallet when requested by wallet model
|
||||
if(walletModel->getEncryptionStatus() == WalletModel::Locked)
|
||||
{
|
||||
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
|
||||
dlg.setModel(walletModel);
|
||||
dlg.exec();
|
||||
}
|
||||
walletFrame->unlockWallet();
|
||||
}
|
||||
|
||||
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
|
||||
|
|
|
@ -3,10 +3,14 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QMap>
|
||||
|
||||
class TransactionTableModel;
|
||||
class WalletFrame;
|
||||
class WalletView;
|
||||
class ClientModel;
|
||||
class WalletModel;
|
||||
class WalletStack;
|
||||
class TransactionView;
|
||||
class OverviewPage;
|
||||
class AddressBookPage;
|
||||
|
@ -15,11 +19,16 @@ class SignVerifyMessageDialog;
|
|||
class Notificator;
|
||||
class RPCConsole;
|
||||
|
||||
class CWallet;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
class QProgressBar;
|
||||
class QStackedWidget;
|
||||
class QUrl;
|
||||
class QListWidget;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/**
|
||||
|
@ -31,6 +40,8 @@ class BitcoinGUI : public QMainWindow
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static const QString DEFAULT_WALLET;
|
||||
|
||||
explicit BitcoinGUI(QWidget *parent = 0);
|
||||
~BitcoinGUI();
|
||||
|
||||
|
@ -42,7 +53,11 @@ public:
|
|||
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
|
||||
functionality.
|
||||
*/
|
||||
void setWalletModel(WalletModel *walletModel);
|
||||
|
||||
bool addWallet(const QString& name, WalletModel *walletModel);
|
||||
bool setCurrentWallet(const QString& name);
|
||||
|
||||
void removeAllWallets();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
@ -53,16 +68,7 @@ protected:
|
|||
|
||||
private:
|
||||
ClientModel *clientModel;
|
||||
WalletModel *walletModel;
|
||||
|
||||
QStackedWidget *centralWidget;
|
||||
|
||||
OverviewPage *overviewPage;
|
||||
QWidget *transactionsPage;
|
||||
AddressBookPage *addressBookPage;
|
||||
AddressBookPage *receiveCoinsPage;
|
||||
SendCoinsDialog *sendCoinsPage;
|
||||
SignVerifyMessageDialog *signVerifyMessageDialog;
|
||||
WalletFrame *walletFrame;
|
||||
|
||||
QLabel *labelEncryptionIcon;
|
||||
QLabel *labelConnectionsIcon;
|
||||
|
@ -88,7 +94,7 @@ private:
|
|||
QAction *changePassphraseAction;
|
||||
QAction *aboutQtAction;
|
||||
QAction *openRPCConsoleAction;
|
||||
|
||||
|
||||
QSystemTrayIcon *trayIcon;
|
||||
Notificator *notificator;
|
||||
TransactionView *transactionView;
|
||||
|
@ -139,6 +145,9 @@ public slots:
|
|||
void askFee(qint64 nFeeRequired, bool *payFee);
|
||||
void handleURI(QString strURI);
|
||||
|
||||
/** Show incoming transaction notification for new transactions. */
|
||||
void incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address);
|
||||
|
||||
private slots:
|
||||
/** Switch to overview (home) page */
|
||||
void gotoOverviewPage();
|
||||
|
@ -149,7 +158,7 @@ private slots:
|
|||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
void gotoSendCoinsPage(QString addr = "");
|
||||
void gotoSendCoinsPage();
|
||||
|
||||
/** Show Sign/Verify Message dialog and switch to sign message tab */
|
||||
void gotoSignMessageTab(QString addr = "");
|
||||
|
@ -164,11 +173,6 @@ private slots:
|
|||
/** Handle tray icon clicked */
|
||||
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
|
||||
#endif
|
||||
/** Show incoming transaction notification for new transactions.
|
||||
|
||||
The new items are those between start and end inclusive, under the given parent item.
|
||||
*/
|
||||
void incomingTransaction(const QModelIndex& parent, int start, int /*end*/);
|
||||
/** Encrypt the wallet */
|
||||
void encryptWallet(bool status);
|
||||
/** Backup the wallet */
|
||||
|
|
129
src/qt/walletframe.cpp
Normal file
129
src/qt/walletframe.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2013
|
||||
*/
|
||||
#include "walletframe.h"
|
||||
#include "bitcoingui.h"
|
||||
#include "walletstack.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
WalletFrame::WalletFrame(BitcoinGUI *_gui) :
|
||||
QFrame(_gui),
|
||||
gui(_gui),
|
||||
clientModel(0)
|
||||
{
|
||||
// Leave HBox hook for adding a list view later
|
||||
QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
|
||||
walletStack = new WalletStack(this);
|
||||
walletStack->setBitcoinGUI(gui);
|
||||
walletFrameLayout->addWidget(walletStack);
|
||||
}
|
||||
|
||||
WalletFrame::~WalletFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void WalletFrame::setClientModel(ClientModel *clientModel)
|
||||
{
|
||||
this->clientModel = clientModel;
|
||||
walletStack->setClientModel(clientModel);
|
||||
}
|
||||
|
||||
bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
|
||||
{
|
||||
return walletStack->addWallet(name, walletModel);
|
||||
}
|
||||
|
||||
bool WalletFrame::setCurrentWallet(const QString& name)
|
||||
{
|
||||
// TODO: Check if valid name
|
||||
walletStack->setCurrentWallet(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WalletFrame::removeAllWallets()
|
||||
{
|
||||
walletStack->removeAllWallets();
|
||||
}
|
||||
|
||||
bool WalletFrame::handleURI(const QString &uri)
|
||||
{
|
||||
return walletStack->handleURI(uri);
|
||||
}
|
||||
|
||||
void WalletFrame::showOutOfSyncWarning(bool fShow)
|
||||
{
|
||||
if (!walletStack) {
|
||||
QMessageBox box;
|
||||
box.setText("walletStack is null");
|
||||
box.exec();
|
||||
return;
|
||||
}
|
||||
walletStack->showOutOfSyncWarning(fShow);
|
||||
}
|
||||
|
||||
void WalletFrame::gotoOverviewPage()
|
||||
{
|
||||
walletStack->gotoOverviewPage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoHistoryPage()
|
||||
{
|
||||
walletStack->gotoHistoryPage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoAddressBookPage()
|
||||
{
|
||||
walletStack->gotoAddressBookPage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoReceiveCoinsPage()
|
||||
{
|
||||
walletStack->gotoReceiveCoinsPage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoSendCoinsPage()
|
||||
{
|
||||
walletStack->gotoSendCoinsPage();
|
||||
}
|
||||
|
||||
void WalletFrame::gotoSignMessageTab(QString addr)
|
||||
{
|
||||
walletStack->gotoSignMessageTab(addr);
|
||||
}
|
||||
|
||||
void WalletFrame::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
walletStack->gotoSignMessageTab(addr);
|
||||
}
|
||||
|
||||
void WalletFrame::encryptWallet(bool status)
|
||||
{
|
||||
walletStack->encryptWallet(status);
|
||||
}
|
||||
|
||||
void WalletFrame::backupWallet()
|
||||
{
|
||||
walletStack->backupWallet();
|
||||
}
|
||||
|
||||
void WalletFrame::changePassphrase()
|
||||
{
|
||||
walletStack->changePassphrase();
|
||||
}
|
||||
|
||||
void WalletFrame::unlockWallet()
|
||||
{
|
||||
walletStack->unlockWallet();
|
||||
}
|
||||
|
||||
void WalletFrame::setEncryptionStatus()
|
||||
{
|
||||
walletStack->setEncryptionStatus();
|
||||
}
|
73
src/qt/walletframe.h
Normal file
73
src/qt/walletframe.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2013
|
||||
*/
|
||||
#ifndef WALLETFRAME_H
|
||||
#define WALLETFRAME_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
class BitcoinGUI;
|
||||
class ClientModel;
|
||||
class WalletModel;
|
||||
class WalletStack;
|
||||
|
||||
class WalletFrame : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WalletFrame(BitcoinGUI *_gui);
|
||||
~WalletFrame();
|
||||
|
||||
void setClientModel(ClientModel *clientModel);
|
||||
|
||||
bool addWallet(const QString& name, WalletModel *walletModel);
|
||||
bool setCurrentWallet(const QString& name);
|
||||
|
||||
void removeAllWallets();
|
||||
|
||||
bool handleURI(const QString &uri);
|
||||
|
||||
void showOutOfSyncWarning(bool fShow);
|
||||
|
||||
private:
|
||||
BitcoinGUI *gui;
|
||||
ClientModel *clientModel;
|
||||
WalletStack *walletStack;
|
||||
|
||||
public slots:
|
||||
/** Switch to overview (home) page */
|
||||
void gotoOverviewPage();
|
||||
/** Switch to history (transactions) page */
|
||||
void gotoHistoryPage();
|
||||
/** Switch to address book page */
|
||||
void gotoAddressBookPage();
|
||||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
void gotoSendCoinsPage();
|
||||
|
||||
/** Show Sign/Verify Message dialog and switch to sign message tab */
|
||||
void gotoSignMessageTab(QString addr = "");
|
||||
/** Show Sign/Verify Message dialog and switch to verify message tab */
|
||||
void gotoVerifyMessageTab(QString addr = "");
|
||||
|
||||
/** Encrypt the wallet */
|
||||
void encryptWallet(bool status);
|
||||
/** Backup the wallet */
|
||||
void backupWallet();
|
||||
/** Change encrypted wallet passphrase */
|
||||
void changePassphrase();
|
||||
/** Ask for passphrase to unlock wallet temporarily */
|
||||
void unlockWallet();
|
||||
|
||||
/** Set the encryption status as shown in the UI.
|
||||
@param[in] status current encryption status
|
||||
@see WalletModel::EncryptionStatus
|
||||
*/
|
||||
void setEncryptionStatus();
|
||||
};
|
||||
|
||||
#endif // WALLETFRAME_H
|
155
src/qt/walletstack.cpp
Normal file
155
src/qt/walletstack.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2013
|
||||
*/
|
||||
#include "walletstack.h"
|
||||
#include "walletview.h"
|
||||
#include "bitcoingui.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QMessageBox>
|
||||
|
||||
WalletStack::WalletStack(QWidget *parent) :
|
||||
QStackedWidget(parent),
|
||||
clientModel(0),
|
||||
bOutOfSync(true)
|
||||
{
|
||||
}
|
||||
|
||||
WalletStack::~WalletStack()
|
||||
{
|
||||
}
|
||||
|
||||
bool WalletStack::addWallet(const QString& name, WalletModel *walletModel)
|
||||
{
|
||||
if (!gui || !clientModel || mapWalletViews.count(name) > 0)
|
||||
return false;
|
||||
|
||||
WalletView *walletView = new WalletView(this, gui);
|
||||
walletView->setBitcoinGUI(gui);
|
||||
walletView->setClientModel(clientModel);
|
||||
walletView->setWalletModel(walletModel);
|
||||
walletView->showOutOfSyncWarning(bOutOfSync);
|
||||
addWidget(walletView);
|
||||
mapWalletViews[name] = walletView;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalletStack::removeWallet(const QString& name)
|
||||
{
|
||||
if (mapWalletViews.count(name) == 0) return false;
|
||||
WalletView *walletView = mapWalletViews.take(name);
|
||||
removeWidget(walletView);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WalletStack::removeAllWallets()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
removeWidget(i.value());
|
||||
mapWalletViews.clear();
|
||||
}
|
||||
|
||||
bool WalletStack::handleURI(const QString &uri)
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (!walletView) return false;
|
||||
|
||||
return walletView->handleURI(uri);
|
||||
}
|
||||
|
||||
void WalletStack::showOutOfSyncWarning(bool fShow)
|
||||
{
|
||||
bOutOfSync = fShow;
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->showOutOfSyncWarning(fShow);
|
||||
}
|
||||
|
||||
void WalletStack::gotoOverviewPage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->gotoOverviewPage();
|
||||
}
|
||||
|
||||
void WalletStack::gotoHistoryPage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->gotoHistoryPage();
|
||||
}
|
||||
|
||||
void WalletStack::gotoAddressBookPage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->gotoAddressBookPage();
|
||||
}
|
||||
|
||||
void WalletStack::gotoReceiveCoinsPage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->gotoReceiveCoinsPage();
|
||||
}
|
||||
|
||||
void WalletStack::gotoSendCoinsPage()
|
||||
{
|
||||
QMap<QString, WalletView*>::const_iterator i;
|
||||
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
|
||||
i.value()->gotoSendCoinsPage();
|
||||
}
|
||||
|
||||
void WalletStack::gotoSignMessageTab(QString addr)
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->gotoSignMessageTab(addr);
|
||||
}
|
||||
|
||||
void WalletStack::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->gotoVerifyMessageTab(addr);
|
||||
}
|
||||
|
||||
void WalletStack::encryptWallet(bool status)
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->encryptWallet(status);
|
||||
}
|
||||
|
||||
void WalletStack::backupWallet()
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->backupWallet();
|
||||
}
|
||||
|
||||
void WalletStack::changePassphrase()
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->changePassphrase();
|
||||
}
|
||||
|
||||
void WalletStack::unlockWallet()
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->unlockWallet();
|
||||
}
|
||||
|
||||
void WalletStack::setEncryptionStatus()
|
||||
{
|
||||
WalletView *walletView = (WalletView*)currentWidget();
|
||||
if (walletView) walletView->setEncryptionStatus();
|
||||
}
|
||||
|
||||
void WalletStack::setCurrentWallet(const QString& name)
|
||||
{
|
||||
if (mapWalletViews.count(name) == 0) return;
|
||||
WalletView *walletView = mapWalletViews.value(name);
|
||||
setCurrentWidget(walletView);
|
||||
walletView->setEncryptionStatus();
|
||||
}
|
102
src/qt/walletstack.h
Normal file
102
src/qt/walletstack.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2013
|
||||
*/
|
||||
#ifndef WALLETSTACK_H
|
||||
#define WALLETSTACK_H
|
||||
|
||||
#include <QStackedWidget>
|
||||
#include <QMap>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class BitcoinGUI;
|
||||
class TransactionTableModel;
|
||||
class ClientModel;
|
||||
class WalletModel;
|
||||
class WalletView;
|
||||
class TransactionView;
|
||||
class OverviewPage;
|
||||
class AddressBookPage;
|
||||
class SendCoinsDialog;
|
||||
class SignVerifyMessageDialog;
|
||||
class Notificator;
|
||||
class RPCConsole;
|
||||
|
||||
class CWalletManager;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/*
|
||||
WalletStack class. This class is a container for WalletView instances. It takes the place of centralWidget.
|
||||
It was added to support multiple wallet functionality. It communicates with both the client and the
|
||||
wallet models to give the user an up-to-date view of the current core state. It manages all the wallet views
|
||||
it contains and updates them accordingly.
|
||||
*/
|
||||
class WalletStack : public QStackedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WalletStack(QWidget *parent = 0);
|
||||
~WalletStack();
|
||||
|
||||
void setBitcoinGUI(BitcoinGUI *gui) { this->gui = gui; }
|
||||
|
||||
void setClientModel(ClientModel *clientModel) { this->clientModel = clientModel; }
|
||||
|
||||
bool addWallet(const QString& name, WalletModel *walletModel);
|
||||
bool removeWallet(const QString& name);
|
||||
|
||||
void removeAllWallets();
|
||||
|
||||
bool handleURI(const QString &uri);
|
||||
|
||||
void showOutOfSyncWarning(bool fShow);
|
||||
|
||||
private:
|
||||
BitcoinGUI *gui;
|
||||
ClientModel *clientModel;
|
||||
QMap<QString, WalletView*> mapWalletViews;
|
||||
|
||||
bool bOutOfSync;
|
||||
|
||||
public slots:
|
||||
void setCurrentWallet(const QString& name);
|
||||
|
||||
/** Switch to overview (home) page */
|
||||
void gotoOverviewPage();
|
||||
/** Switch to history (transactions) page */
|
||||
void gotoHistoryPage();
|
||||
/** Switch to address book page */
|
||||
void gotoAddressBookPage();
|
||||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
void gotoSendCoinsPage();
|
||||
|
||||
/** Show Sign/Verify Message dialog and switch to sign message tab */
|
||||
void gotoSignMessageTab(QString addr = "");
|
||||
/** Show Sign/Verify Message dialog and switch to verify message tab */
|
||||
void gotoVerifyMessageTab(QString addr = "");
|
||||
|
||||
/** Encrypt the wallet */
|
||||
void encryptWallet(bool status);
|
||||
/** Backup the wallet */
|
||||
void backupWallet();
|
||||
/** Change encrypted wallet passphrase */
|
||||
void changePassphrase();
|
||||
/** Ask for passphrase to unlock wallet temporarily */
|
||||
void unlockWallet();
|
||||
|
||||
/** Set the encryption status as shown in the UI.
|
||||
@param[in] status current encryption status
|
||||
@see WalletModel::EncryptionStatus
|
||||
*/
|
||||
void setEncryptionStatus();
|
||||
};
|
||||
|
||||
#endif // WALLETSTACK_H
|
354
src/qt/walletview.cpp
Normal file
354
src/qt/walletview.cpp
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2013
|
||||
*/
|
||||
#include "walletview.h"
|
||||
#include "bitcoingui.h"
|
||||
#include "transactiontablemodel.h"
|
||||
#include "addressbookpage.h"
|
||||
#include "sendcoinsdialog.h"
|
||||
#include "signverifymessagedialog.h"
|
||||
#include "optionsdialog.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "clientmodel.h"
|
||||
#include "walletmodel.h"
|
||||
#include "editaddressdialog.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "transactiondescdialog.h"
|
||||
#include "addresstablemodel.h"
|
||||
#include "transactionview.h"
|
||||
#include "overviewpage.h"
|
||||
#include "bitcoinunits.h"
|
||||
#include "guiconstants.h"
|
||||
#include "askpassphrasedialog.h"
|
||||
#include "guiutil.h"
|
||||
#include "ui_interface.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QActionGroup>
|
||||
#include <QAction>
|
||||
#include <QLabel>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
|
||||
WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui):
|
||||
QStackedWidget(parent),
|
||||
gui(_gui),
|
||||
clientModel(0),
|
||||
walletModel(0),
|
||||
encryptWalletAction(0),
|
||||
changePassphraseAction(0)
|
||||
{
|
||||
// Create actions for the toolbar, menu bar and tray/dock icon
|
||||
createActions();
|
||||
|
||||
// Create tabs
|
||||
overviewPage = new OverviewPage();
|
||||
|
||||
transactionsPage = new QWidget(this);
|
||||
QVBoxLayout *vbox = new QVBoxLayout();
|
||||
transactionView = new TransactionView(this);
|
||||
vbox->addWidget(transactionView);
|
||||
transactionsPage->setLayout(vbox);
|
||||
|
||||
addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab);
|
||||
|
||||
receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab);
|
||||
|
||||
sendCoinsPage = new SendCoinsDialog(gui);
|
||||
|
||||
signVerifyMessageDialog = new SignVerifyMessageDialog(gui);
|
||||
|
||||
addWidget(overviewPage);
|
||||
addWidget(transactionsPage);
|
||||
addWidget(addressBookPage);
|
||||
addWidget(receiveCoinsPage);
|
||||
addWidget(sendCoinsPage);
|
||||
|
||||
// Clicking on a transaction on the overview page simply sends you to transaction history page
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage()));
|
||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
|
||||
|
||||
// Double-clicking on a transaction on the transaction history page shows details
|
||||
connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));
|
||||
|
||||
// Clicking on "Verify Message" in the address book sends you to the verify message tab
|
||||
connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString)));
|
||||
// Clicking on "Sign Message" in the receive coins page sends you to the sign message tab
|
||||
connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString)));
|
||||
|
||||
gotoOverviewPage();
|
||||
}
|
||||
|
||||
WalletView::~WalletView()
|
||||
{
|
||||
}
|
||||
|
||||
void WalletView::createActions()
|
||||
{
|
||||
QActionGroup *tabGroup = new QActionGroup(this);
|
||||
|
||||
overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
|
||||
overviewAction->setStatusTip(tr("Show general overview of wallet"));
|
||||
overviewAction->setToolTip(overviewAction->statusTip());
|
||||
overviewAction->setCheckable(true);
|
||||
overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
|
||||
tabGroup->addAction(overviewAction);
|
||||
|
||||
sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
|
||||
sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
|
||||
sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
|
||||
sendCoinsAction->setCheckable(true);
|
||||
sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
|
||||
tabGroup->addAction(sendCoinsAction);
|
||||
|
||||
receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
|
||||
receiveCoinsAction->setStatusTip(tr("Show the list of addresses for receiving payments"));
|
||||
receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
|
||||
receiveCoinsAction->setCheckable(true);
|
||||
receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
|
||||
tabGroup->addAction(receiveCoinsAction);
|
||||
|
||||
historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
|
||||
historyAction->setStatusTip(tr("Browse transaction history"));
|
||||
historyAction->setToolTip(historyAction->statusTip());
|
||||
historyAction->setCheckable(true);
|
||||
historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
|
||||
tabGroup->addAction(historyAction);
|
||||
|
||||
addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
|
||||
addressBookAction->setStatusTip(tr("Edit the list of stored addresses and labels"));
|
||||
addressBookAction->setToolTip(addressBookAction->statusTip());
|
||||
addressBookAction->setCheckable(true);
|
||||
addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
|
||||
tabGroup->addAction(addressBookAction);
|
||||
|
||||
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
|
||||
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
|
||||
connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
|
||||
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
|
||||
connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
|
||||
|
||||
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
|
||||
encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
|
||||
encryptWalletAction->setCheckable(true);
|
||||
backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
|
||||
backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
|
||||
changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
|
||||
changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
|
||||
signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
|
||||
signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
|
||||
verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
|
||||
verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
|
||||
|
||||
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
|
||||
exportAction->setStatusTip(tr("Export the data in the current tab to a file"));
|
||||
exportAction->setToolTip(exportAction->statusTip());
|
||||
|
||||
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
|
||||
connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
|
||||
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
|
||||
connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
|
||||
connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
|
||||
}
|
||||
|
||||
void WalletView::setBitcoinGUI(BitcoinGUI *gui)
|
||||
{
|
||||
this->gui = gui;
|
||||
}
|
||||
|
||||
void WalletView::setClientModel(ClientModel *clientModel)
|
||||
{
|
||||
this->clientModel = clientModel;
|
||||
if(clientModel)
|
||||
{
|
||||
overviewPage->setClientModel(clientModel);
|
||||
addressBookPage->setOptionsModel(clientModel->getOptionsModel());
|
||||
receiveCoinsPage->setOptionsModel(clientModel->getOptionsModel());
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::setWalletModel(WalletModel *walletModel)
|
||||
{
|
||||
this->walletModel = walletModel;
|
||||
if(walletModel)
|
||||
{
|
||||
// Receive and report messages from wallet thread
|
||||
connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));
|
||||
|
||||
// Put transaction list in tabs
|
||||
transactionView->setModel(walletModel);
|
||||
overviewPage->setWalletModel(walletModel);
|
||||
addressBookPage->setModel(walletModel->getAddressTableModel());
|
||||
receiveCoinsPage->setModel(walletModel->getAddressTableModel());
|
||||
sendCoinsPage->setModel(walletModel);
|
||||
signVerifyMessageDialog->setModel(walletModel);
|
||||
|
||||
setEncryptionStatus();
|
||||
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));
|
||||
|
||||
// Balloon pop-up for new transaction
|
||||
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
|
||||
this, SLOT(incomingTransaction(QModelIndex,int,int)));
|
||||
|
||||
// Ask for passphrase if needed
|
||||
connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::incomingTransaction(const QModelIndex& parent, int start, int /*end*/)
|
||||
{
|
||||
// Prevent balloon-spam when initial block download is in progress
|
||||
if(!walletModel || !clientModel || clientModel->inInitialBlockDownload())
|
||||
return;
|
||||
|
||||
TransactionTableModel *ttm = walletModel->getTransactionTableModel();
|
||||
|
||||
QString date = ttm->index(start, TransactionTableModel::Date, parent)
|
||||
.data().toString();
|
||||
qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
|
||||
.data(Qt::EditRole).toULongLong();
|
||||
QString type = ttm->index(start, TransactionTableModel::Type, parent)
|
||||
.data().toString();
|
||||
QString address = ttm->index(start, TransactionTableModel::ToAddress, parent)
|
||||
.data().toString();
|
||||
|
||||
gui->incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
|
||||
}
|
||||
|
||||
void WalletView::gotoOverviewPage()
|
||||
{
|
||||
overviewAction->setChecked(true);
|
||||
setCurrentWidget(overviewPage);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
}
|
||||
|
||||
void WalletView::gotoHistoryPage()
|
||||
{
|
||||
historyAction->setChecked(true);
|
||||
setCurrentWidget(transactionsPage);
|
||||
|
||||
exportAction->setEnabled(true);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked()));
|
||||
}
|
||||
|
||||
void WalletView::gotoAddressBookPage()
|
||||
{
|
||||
addressBookAction->setChecked(true);
|
||||
setCurrentWidget(addressBookPage);
|
||||
|
||||
exportAction->setEnabled(true);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked()));
|
||||
}
|
||||
|
||||
void WalletView::gotoReceiveCoinsPage()
|
||||
{
|
||||
receiveCoinsAction->setChecked(true);
|
||||
setCurrentWidget(receiveCoinsPage);
|
||||
|
||||
exportAction->setEnabled(true);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked()));
|
||||
}
|
||||
|
||||
void WalletView::gotoSendCoinsPage()
|
||||
{
|
||||
sendCoinsAction->setChecked(true);
|
||||
setCurrentWidget(sendCoinsPage);
|
||||
|
||||
exportAction->setEnabled(false);
|
||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||
}
|
||||
|
||||
void WalletView::gotoSignMessageTab(QString addr)
|
||||
{
|
||||
// call show() in showTab_SM()
|
||||
signVerifyMessageDialog->showTab_SM(true);
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_SM(addr);
|
||||
}
|
||||
|
||||
void WalletView::gotoVerifyMessageTab(QString addr)
|
||||
{
|
||||
// call show() in showTab_VM()
|
||||
signVerifyMessageDialog->showTab_VM(true);
|
||||
|
||||
if(!addr.isEmpty())
|
||||
signVerifyMessageDialog->setAddress_VM(addr);
|
||||
}
|
||||
|
||||
bool WalletView::handleURI(const QString& strURI)
|
||||
{
|
||||
// URI has to be valid
|
||||
if (sendCoinsPage->handleURI(strURI))
|
||||
{
|
||||
gotoSendCoinsPage();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void WalletView::showOutOfSyncWarning(bool fShow)
|
||||
{
|
||||
overviewPage->showOutOfSyncWarning(fShow);
|
||||
}
|
||||
|
||||
void WalletView::setEncryptionStatus()
|
||||
{
|
||||
gui->setEncryptionStatus(walletModel->getEncryptionStatus());
|
||||
}
|
||||
|
||||
void WalletView::encryptWallet(bool status)
|
||||
{
|
||||
if(!walletModel)
|
||||
return;
|
||||
AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt:
|
||||
AskPassphraseDialog::Decrypt, this);
|
||||
dlg.setModel(walletModel);
|
||||
dlg.exec();
|
||||
|
||||
setEncryptionStatus();
|
||||
}
|
||||
|
||||
void WalletView::backupWallet()
|
||||
{
|
||||
QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
|
||||
QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
|
||||
if(!filename.isEmpty()) {
|
||||
if(!walletModel->backupWallet(filename)) {
|
||||
gui->message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
else
|
||||
gui->message(tr("Backup Successful"), tr("The wallet data was successfully saved to the new location."),
|
||||
CClientUIInterface::MSG_INFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
void WalletView::changePassphrase()
|
||||
{
|
||||
AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
|
||||
dlg.setModel(walletModel);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void WalletView::unlockWallet()
|
||||
{
|
||||
if(!walletModel)
|
||||
return;
|
||||
// Unlock wallet when requested by wallet model
|
||||
if(walletModel->getEncryptionStatus() == WalletModel::Locked)
|
||||
{
|
||||
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
|
||||
dlg.setModel(walletModel);
|
||||
dlg.exec();
|
||||
}
|
||||
}
|
132
src/qt/walletview.h
Normal file
132
src/qt/walletview.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Qt4 bitcoin GUI.
|
||||
*
|
||||
* W.J. van der Laan 2011-2012
|
||||
* The Bitcoin Developers 2011-2013
|
||||
*/
|
||||
#ifndef WALLETVIEW_H
|
||||
#define WALLETVIEW_H
|
||||
|
||||
#include <QStackedWidget>
|
||||
|
||||
class BitcoinGUI;
|
||||
class TransactionTableModel;
|
||||
class ClientModel;
|
||||
class WalletModel;
|
||||
class TransactionView;
|
||||
class OverviewPage;
|
||||
class AddressBookPage;
|
||||
class SendCoinsDialog;
|
||||
class SignVerifyMessageDialog;
|
||||
class Notificator;
|
||||
class RPCConsole;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QLabel;
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/*
|
||||
WalletView class. This class represents the view to a single wallet.
|
||||
It was added to support multiple wallet functionality. Each wallet gets its own WalletView instance.
|
||||
It communicates with both the client and the wallet models to give the user an up-to-date view of the
|
||||
current core state.
|
||||
*/
|
||||
class WalletView : public QStackedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WalletView(QWidget *parent, BitcoinGUI *_gui);
|
||||
~WalletView();
|
||||
|
||||
void setBitcoinGUI(BitcoinGUI *gui);
|
||||
/** Set the client model.
|
||||
The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic.
|
||||
*/
|
||||
void setClientModel(ClientModel *clientModel);
|
||||
/** Set the wallet model.
|
||||
The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending
|
||||
functionality.
|
||||
*/
|
||||
void setWalletModel(WalletModel *walletModel);
|
||||
|
||||
bool handleURI(const QString &uri);
|
||||
|
||||
void showOutOfSyncWarning(bool fShow);
|
||||
|
||||
private:
|
||||
BitcoinGUI *gui;
|
||||
ClientModel *clientModel;
|
||||
WalletModel *walletModel;
|
||||
|
||||
OverviewPage *overviewPage;
|
||||
QWidget *transactionsPage;
|
||||
AddressBookPage *addressBookPage;
|
||||
AddressBookPage *receiveCoinsPage;
|
||||
SendCoinsDialog *sendCoinsPage;
|
||||
SignVerifyMessageDialog *signVerifyMessageDialog;
|
||||
|
||||
QLabel *labelEncryptionIcon;
|
||||
QLabel *labelConnectionsIcon;
|
||||
QLabel *labelBlocksIcon;
|
||||
QLabel *progressBarLabel;
|
||||
|
||||
QAction *overviewAction;
|
||||
QAction *historyAction;
|
||||
QAction *quitAction;
|
||||
QAction *sendCoinsAction;
|
||||
QAction *addressBookAction;
|
||||
QAction *signMessageAction;
|
||||
QAction *verifyMessageAction;
|
||||
QAction *aboutAction;
|
||||
QAction *receiveCoinsAction;
|
||||
QAction *optionsAction;
|
||||
QAction *toggleHideAction;
|
||||
QAction *exportAction;
|
||||
QAction *encryptWalletAction;
|
||||
QAction *backupWalletAction;
|
||||
QAction *changePassphraseAction;
|
||||
QAction *aboutQtAction;
|
||||
QAction *openRPCConsoleAction;
|
||||
|
||||
TransactionView *transactionView;
|
||||
|
||||
/** Create the main UI actions. */
|
||||
void createActions();
|
||||
/** Create the menu bar and sub-menus. */
|
||||
|
||||
public slots:
|
||||
/** Switch to overview (home) page */
|
||||
void gotoOverviewPage();
|
||||
/** Switch to history (transactions) page */
|
||||
void gotoHistoryPage();
|
||||
/** Switch to address book page */
|
||||
void gotoAddressBookPage();
|
||||
/** Switch to receive coins page */
|
||||
void gotoReceiveCoinsPage();
|
||||
/** Switch to send coins page */
|
||||
void gotoSendCoinsPage();
|
||||
|
||||
/** Show Sign/Verify Message dialog and switch to sign message tab */
|
||||
void gotoSignMessageTab(QString addr = "");
|
||||
/** Show Sign/Verify Message dialog and switch to verify message tab */
|
||||
void gotoVerifyMessageTab(QString addr = "");
|
||||
|
||||
/** Show incoming transaction notification for new transactions.
|
||||
|
||||
The new items are those between start and end inclusive, under the given parent item.
|
||||
*/
|
||||
void incomingTransaction(const QModelIndex& parent, int start, int /*end*/);
|
||||
/** Encrypt the wallet */
|
||||
void encryptWallet(bool status);
|
||||
/** Backup the wallet */
|
||||
void backupWallet();
|
||||
/** Change encrypted wallet passphrase */
|
||||
void changePassphrase();
|
||||
/** Ask for passphrase to unlock wallet temporarily */
|
||||
void unlockWallet();
|
||||
|
||||
void setEncryptionStatus();
|
||||
};
|
||||
|
||||
#endif // WALLETVIEW_H
|
Loading…
Reference in a new issue