aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro6
-rw-r--r--multiwallet-qt.txt53
-rw-r--r--src/qt/bitcoin.cpp5
-rw-r--r--src/qt/bitcoingui.cpp278
-rw-r--r--src/qt/bitcoingui.h40
-rw-r--r--src/qt/walletframe.cpp129
-rw-r--r--src/qt/walletframe.h73
-rw-r--r--src/qt/walletstack.cpp155
-rw-r--r--src/qt/walletstack.h102
-rw-r--r--src/qt/walletview.cpp354
-rw-r--r--src/qt/walletview.h132
11 files changed, 1099 insertions, 228 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index bf41314052..d518cf3b16 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -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 \
diff --git a/multiwallet-qt.txt b/multiwallet-qt.txt
new file mode 100644
index 0000000000..8394080db0
--- /dev/null
+++ b/multiwallet-qt.txt
@@ -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();
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index e3d51be54a..346128c0c4 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -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
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index b9cd7f51d2..eff8e667f6 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -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"
@@ -56,13 +50,15 @@
#include <QStyle>
#include <QSettings>
#include <QDesktopWidget>
+#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),
@@ -95,31 +91,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();
@@ -164,27 +139,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()
@@ -246,7 +205,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));
@@ -380,39 +339,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)));
-
- // 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(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()));
- }
+ return walletFrame->addWallet(name, walletModel);
+}
+
+bool BitcoinGUI::setCurrentWallet(const QString& name)
+{
+ return walletFrame->setCurrentWallet(name);
+}
+
+void BitcoinGUI::removeAllWallets()
+{
+ walletFrame->removeAllWallets();
}
void BitcoinGUI::createTrayIcon()
@@ -509,6 +452,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;
@@ -573,7 +551,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);
@@ -608,7 +586,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);
@@ -717,104 +695,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
@@ -830,13 +724,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);
@@ -860,12 +754,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);
}
@@ -901,49 +790,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)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index af8dc0a1fe..750e97104c 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -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;
@@ -143,6 +149,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();
@@ -153,7 +162,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 = "");
@@ -168,11 +177,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 */
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
new file mode 100644
index 0000000000..a53aa65466
--- /dev/null
+++ b/src/qt/walletframe.cpp
@@ -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();
+}
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
new file mode 100644
index 0000000000..5b4baf7255
--- /dev/null
+++ b/src/qt/walletframe.h
@@ -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 \ No newline at end of file
diff --git a/src/qt/walletstack.cpp b/src/qt/walletstack.cpp
new file mode 100644
index 0000000000..271d1c7924
--- /dev/null
+++ b/src/qt/walletstack.cpp
@@ -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();
+}
diff --git a/src/qt/walletstack.h b/src/qt/walletstack.h
new file mode 100644
index 0000000000..f3485816e9
--- /dev/null
+++ b/src/qt/walletstack.h
@@ -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
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
new file mode 100644
index 0000000000..7dd36234c9
--- /dev/null
+++ b/src/qt/walletview.cpp
@@ -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();
+ }
+}
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
new file mode 100644
index 0000000000..38eb0227af
--- /dev/null
+++ b/src/qt/walletview.h
@@ -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