src/key.h \
src/db.h \
src/script.h \
- src/noui.h \
src/init.h \
src/headers.h \
src/irc.h \
src/qt/guiconstants.h \
src/qt/optionsmodel.h \
src/qt/monitoreddatamapper.h \
- src/qtui.h \
src/qt/transactiondesc.h \
src/qt/transactiondescdialog.h \
src/qt/bitcoinamountfield.h \
src/qt/askpassphrasedialog.h \
src/protocol.h \
src/qt/notificator.h \
- src/qt/qtipcserver.h
+ src/qt/qtipcserver.h \
+ src/allocators.h \
+ src/ui_interface.h
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiontablemodel.cpp \
--- /dev/null
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_ALLOCATORS_H
+#define BITCOIN_ALLOCATORS_H
+
+#include <string>
+
+#ifdef WIN32
+#define _WIN32_WINNT 0x0501
+#define WIN32_LEAN_AND_MEAN 1
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+// This is used to attempt to keep keying material out of swap
+// Note that VirtualLock does not provide this as a guarantee on Windows,
+// but, in practice, memory that has been VirtualLock'd almost never gets written to
+// the pagefile except in rare circumstances where memory is extremely low.
+#define mlock(p, n) VirtualLock((p), (n));
+#define munlock(p, n) VirtualUnlock((p), (n));
+#else
+#include <sys/mman.h>
+#include <limits.h>
+/* This comes from limits.h if it's not defined there set a sane default */
+#ifndef PAGESIZE
+#include <unistd.h>
+#define PAGESIZE sysconf(_SC_PAGESIZE)
+#endif
+#define mlock(a,b) \
+ mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
+ (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
+#define munlock(a,b) \
+ munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
+ (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
+#endif
+
+//
+// Allocator that locks its contents from being paged
+// out of memory and clears its contents before deletion.
+//
+template<typename T>
+struct secure_allocator : public std::allocator<T>
+{
+ // MSVC8 default copy constructor is broken
+ typedef std::allocator<T> base;
+ typedef typename base::size_type size_type;
+ typedef typename base::difference_type difference_type;
+ typedef typename base::pointer pointer;
+ typedef typename base::const_pointer const_pointer;
+ typedef typename base::reference reference;
+ typedef typename base::const_reference const_reference;
+ typedef typename base::value_type value_type;
+ secure_allocator() throw() {}
+ secure_allocator(const secure_allocator& a) throw() : base(a) {}
+ template <typename U>
+ secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
+ ~secure_allocator() throw() {}
+ template<typename _Other> struct rebind
+ { typedef secure_allocator<_Other> other; };
+
+ T* allocate(std::size_t n, const void *hint = 0)
+ {
+ T *p;
+ p = std::allocator<T>::allocate(n, hint);
+ if (p != NULL)
+ mlock(p, sizeof(T) * n);
+ return p;
+ }
+
+ void deallocate(T* p, std::size_t n)
+ {
+ if (p != NULL)
+ {
+ memset(p, 0, sizeof(T) * n);
+ munlock(p, sizeof(T) * n);
+ }
+ std::allocator<T>::deallocate(p, n);
+ }
+};
+
+
+//
+// Allocator that clears its contents before deletion.
+//
+template<typename T>
+struct zero_after_free_allocator : public std::allocator<T>
+{
+ // MSVC8 default copy constructor is broken
+ typedef std::allocator<T> base;
+ typedef typename base::size_type size_type;
+ typedef typename base::difference_type difference_type;
+ typedef typename base::pointer pointer;
+ typedef typename base::const_pointer const_pointer;
+ typedef typename base::reference reference;
+ typedef typename base::const_reference const_reference;
+ typedef typename base::value_type value_type;
+ zero_after_free_allocator() throw() {}
+ zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
+ template <typename U>
+ zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) {}
+ ~zero_after_free_allocator() throw() {}
+ template<typename _Other> struct rebind
+ { typedef zero_after_free_allocator<_Other> other; };
+
+ void deallocate(T* p, std::size_t n)
+ {
+ if (p != NULL)
+ memset(p, 0, sizeof(T) * n);
+ std::allocator<T>::deallocate(p, n);
+ }
+};
+
+// This is exactly like std::string, but with a custom allocator.
+// (secure_allocator<> is defined in serialize.h)
+typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
+
+#endif
throw runtime_error(
"stop\n"
"Stop bitcoin server.");
-#ifndef QT_GUI
// Shutdown will take long enough that the response should get back
- CreateThread(Shutdown, NULL);
+ QueueShutdown();
return "bitcoin server stopping";
-#else
- throw runtime_error("NYI: cannot shut down GUI with RPC command");
-#endif
}
if (pwalletMain->IsCrypted())
throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
-#ifdef QT_GUI
- // shutting down via RPC while the GUI is running does not work (yet):
- throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
-#endif
-
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
// Alternately, find a way to make params[0] mlock()'d to begin with.
SecureString strWalletPass;
// BDB seems to have a bad habit of writing old data into
// slack space in .dat files; that is bad if the old data is
// unencrypted private keys. So:
- CreateThread(Shutdown, NULL);
+ QueueShutdown();
return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
}
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
else if (mapArgs.count("-daemon"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
- std::string strMessage = _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
- "It is recommended you use the following random password:\n"
- "rpcuser=bitcoinrpc\n"
- "rpcpassword=%s\n"
- "(you do not need to remember this password)\n"
- "If the file does not exist, create it with owner-readable-only file permissions.\n");
- fprintf(stderr, strMessage.c_str(),
+ ThreadSafeMessageBox(strprintf(
+ _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
+ "It is recommended you use the following random password:\n"
+ "rpcuser=bitcoinrpc\n"
+ "rpcpassword=%s\n"
+ "(you do not need to remember this password)\n"
+ "If the file does not exist, create it with owner-readable-only file permissions.\n"),
strWhatAmI.c_str(),
GetConfigFile().c_str(),
- EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str());
-#ifndef QT_GUI
- CreateThread(Shutdown, NULL);
-#endif
+ EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32).c_str()),
+ _("Error"), wxOK | wxMODAL);
+ QueueShutdown();
return;
}
#ifndef __CRYPTER_H__
#define __CRYPTER_H__
-#include "util.h" /* for SecureString */
+#include "allocators.h" /* for SecureString */
#include "key.h"
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
#include "bignum.h"
#include "base58.h"
#include "main.h"
-#ifdef QT_GUI
-#include "qtui.h"
-#else
-#include "noui.h"
-#endif
+#include "wallet.h"
+#include "ui_interface.h"
#include <boost/filesystem/convenience.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
-#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
-#define _BITCOIN_QT_PLUGINS_INCLUDED
-#define __INSURE__
-#include <QtPlugin>
-Q_IMPORT_PLUGIN(qcncodecs)
-Q_IMPORT_PLUGIN(qjpcodecs)
-Q_IMPORT_PLUGIN(qtwcodecs)
-Q_IMPORT_PLUGIN(qkrcodecs)
-Q_IMPORT_PLUGIN(qtaccessiblewidgets)
-#endif
-
#ifdef WIN32
#define strncasecmp strnicmp
#endif
strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end());
#if defined(QT_GUI) && defined(WIN32)
// On windows, show a message box, as there is no stderr
- wxMessageBox(strUsage, "Usage");
+ ThreadSafeMessageBox(strUsage, _("Usage"), wxOK | wxMODAL);
#else
fprintf(stderr, "%s", strUsage.c_str());
#endif
static boost::interprocess::file_lock lock(strLockFile.c_str());
if (!lock.try_lock())
{
- wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin");
+ ThreadSafeMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), _("Bitcoin"), wxOK|wxMODAL);
return false;
}
{
strErrors << _("Wallet needed to be rewritten: restart Bitcoin to complete") << "\n";
printf("%s", strErrors.str().c_str());
- wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
+ ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL);
return false;
}
else
if (!strErrors.str().empty())
{
- wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
+ ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL);
return false;
}
addrProxy = CService(mapArgs["-proxy"], 9050);
if (!addrProxy.IsValid())
{
- wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
+ ThreadSafeMessageBox(_("Invalid -proxy address"), _("Bitcoin"), wxOK | wxMODAL);
return false;
}
}
std::string strError;
if (!BindListenPort(strError))
{
- wxMessageBox(strError, "Bitcoin");
+ ThreadSafeMessageBox(strError, _("Bitcoin"), wxOK | wxMODAL);
return false;
}
}
{
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
{
- wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin");
+ ThreadSafeMessageBox(_("Invalid amount for -paytxfee=<amount>"), _("Bitcoin"), wxOK | wxMODAL);
return false;
}
if (nTransactionFee > 0.25 * COIN)
- wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
+ ThreadSafeMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), _("Bitcoin"), wxOK | wxICON_EXCLAMATION | wxMODAL);
}
//
RandAddSeedPerfmon();
if (!CreateThread(StartNode, NULL))
- wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
+ ThreadSafeMessageBox(_("Error: CreateThread(StartNode) failed"), _("Bitcoin"), wxOK | wxMODAL);
if (fServer)
CreateThread(ThreadRPCServer, NULL);
string strMessage = _("Warning: Disk space is low ");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
- ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
- CreateThread(Shutdown, NULL);
+ ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION | wxMODAL);
+ QueueShutdown();
return false;
}
return true;
dHashesPerSec = 1000.0 * nHashCounter / (GetTimeMillis() - nHPSTimerStart);
nHPSTimerStart = GetTimeMillis();
nHashCounter = 0;
- string strStatus = strprintf(" %.0f khash/s", dHashesPerSec/1000.0);
- UIThreadCall(boost::bind(CalledSetStatusBar, strStatus, 0));
static int64 nLogTime;
if (GetTime() - nLogTime > 30 * 60)
{
vnThreadsRunning[THREAD_MINER]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
- UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
nHPSTimerStart = 0;
if (vnThreadsRunning[THREAD_MINER] == 0)
dHashesPerSec = 0;
obj/rpcdump.o \
obj/script.o \
obj/util.o \
- obj/wallet.o
+ obj/wallet.o \
+ obj/noui.o
all: bitcoind.exe
obj/rpcdump.o \
obj/script.o \
obj/util.o \
- obj/wallet.o
+ obj/wallet.o \
+ obj/noui.o
all: bitcoind.exe
obj/rpcdump.o \
obj/script.o \
obj/util.o \
- obj/wallet.o
+ obj/wallet.o \
+ obj/noui.o
ifdef USE_UPNP
DEFS += -DUSE_UPNP=$(USE_UPNP)
obj/rpcdump.o \
obj/script.o \
obj/util.o \
- obj/wallet.o
+ obj/wallet.o \
+ obj/noui.o
all: bitcoind
--- /dev/null
+// Copyright (c) 2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+#include "ui_interface.h"
+
+#include <string>
+#include "headers.h"
+#include "init.h"
+
+int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
+{
+ printf("%s: %s\n", caption.c_str(), message.c_str());
+ fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
+ return 4;
+}
+
+bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
+{
+ return true;
+}
+
+void MainFrameRepaint()
+{
+}
+
+void AddressBookRepaint()
+{
+}
+
+void InitMessage(const std::string &message)
+{
+}
+
+std::string _(const char* psz)
+{
+ return psz;
+}
+
+void QueueShutdown()
+{
+ // Without UI, Shutdown can simply be started in a new thread
+ CreateThread(Shutdown, NULL);
+}
+
+++ /dev/null
-// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_NOUI_H
-#define BITCOIN_NOUI_H
-
-#include <string>
-#include <boost/function.hpp>
-#include "wallet.h"
-
-typedef void wxWindow;
-#define wxYES 0x00000002
-#define wxOK 0x00000004
-#define wxNO 0x00000008
-#define wxYES_NO (wxYES|wxNO)
-#define wxCANCEL 0x00000010
-#define wxAPPLY 0x00000020
-#define wxCLOSE 0x00000040
-#define wxOK_DEFAULT 0x00000000
-#define wxYES_DEFAULT 0x00000000
-#define wxNO_DEFAULT 0x00000080
-#define wxCANCEL_DEFAULT 0x80000000
-#define wxICON_EXCLAMATION 0x00000100
-#define wxICON_HAND 0x00000200
-#define wxICON_WARNING wxICON_EXCLAMATION
-#define wxICON_ERROR wxICON_HAND
-#define wxICON_QUESTION 0x00000400
-#define wxICON_INFORMATION 0x00000800
-#define wxICON_STOP wxICON_HAND
-#define wxICON_ASTERISK wxICON_INFORMATION
-#define wxICON_MASK (0x00000100|0x00000200|0x00000400|0x00000800)
-#define wxFORWARD 0x00001000
-#define wxBACKWARD 0x00002000
-#define wxRESET 0x00004000
-#define wxHELP 0x00008000
-#define wxMORE 0x00010000
-#define wxSETUP 0x00020000
-
-inline int MyMessageBox(const std::string& message, const std::string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
-{
- printf("%s: %s\n", caption.c_str(), message.c_str());
- fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str());
- return 4;
-}
-#define wxMessageBox MyMessageBox
-
-inline int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1)
-{
- return MyMessageBox(message, caption, style, parent, x, y);
-}
-
-inline bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent)
-{
- return true;
-}
-
-inline void CalledSetStatusBar(const std::string& strText, int nField)
-{
-}
-
-inline void UIThreadCall(boost::function0<void> fn)
-{
-}
-
-inline void MainFrameRepaint()
-{
-}
-
-inline void InitMessage(const std::string &message)
-{
-}
-
-#endif
this->model = model;
if(!model)
return;
- // Refresh list from core
- model->updateList();
proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(model);
}
}
-void AddressTableModel::updateList()
+void AddressTableModel::update()
{
// Update address book model from Bitcoin core
beginResetModel();
{
return QString();
}
- // Add entry and update list
+ // Add entry
CRITICAL_BLOCK(wallet->cs_wallet)
wallet->SetAddressBookName(strAddress, strLabel);
- updateList();
return QString::fromStdString(strAddress);
}
{
wallet->DelAddressBookName(rec->address.toStdString());
}
- updateList();
return true;
}
-void AddressTableModel::update()
-{
-
-}
-
/* Look up label for address in address book, if not found return empty string.
*/
QString AddressTableModel::labelForAddress(const QString &address) const
*/
QString addRow(const QString &type, const QString &label, const QString &address);
- /* Update address list from core. Invalidates any indices.
- */
- void updateList();
-
/* Look up label for address in address book, if not found return empty string.
*/
QString labelForAddress(const QString &address) const;
void defaultAddressChanged(const QString &address);
public slots:
+ /* Update address list from core. Invalidates any indices.
+ */
void update();
};
#include "clientmodel.h"
#include "walletmodel.h"
#include "optionsmodel.h"
+#include "guiutil.h"
#include "headers.h"
#include "init.h"
#include <QApplication>
#include <QMessageBox>
-#include <QThread>
#include <QTextCodec>
#include <QLocale>
#include <QTranslator>
#include <boost/interprocess/ipc/message_queue.hpp>
-// Need a global reference for the notifications to find the GUI
-BitcoinGUI *guiref;
-QSplashScreen *splashref;
+#if defined(BITCOIN_NEED_QT_PLUGINS) && !defined(_BITCOIN_QT_PLUGINS_INCLUDED)
+#define _BITCOIN_QT_PLUGINS_INCLUDED
+#define __INSURE__
+#include <QtPlugin>
+Q_IMPORT_PLUGIN(qcncodecs)
+Q_IMPORT_PLUGIN(qjpcodecs)
+Q_IMPORT_PLUGIN(qtwcodecs)
+Q_IMPORT_PLUGIN(qkrcodecs)
+Q_IMPORT_PLUGIN(qtaccessiblewidgets)
+#endif
-int MyMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
-{
- // Message from AppInit2(), always in main thread before main window is constructed
- QMessageBox::critical(0, QString::fromStdString(caption),
- QString::fromStdString(message),
- QMessageBox::Ok, QMessageBox::Ok);
- return 4;
-}
+// Need a global reference for the notifications to find the GUI
+static BitcoinGUI *guiref;
+static QSplashScreen *splashref;
+static WalletModel *walletmodel;
+static ClientModel *clientmodel;
-int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style, wxWindow* parent, int x, int y)
+int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
{
// Message from network thread
if(guiref)
{
- QMetaObject::invokeMethod(guiref, "error", Qt::QueuedConnection,
+ bool modal = (style & wxMODAL);
+ // in case of modal message, use blocking connection to wait for user to click OK
+ QMetaObject::invokeMethod(guiref, "error",
+ modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(caption)),
- Q_ARG(QString, QString::fromStdString(message)));
+ Q_ARG(QString, QString::fromStdString(message)),
+ Q_ARG(bool, modal));
}
else
{
return 4;
}
-bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent)
+bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
{
if(!guiref)
return false;
return true;
bool payFee = false;
- // Call slot on GUI thread.
- // If called from another thread, use a blocking QueuedConnection.
- Qt::ConnectionType connectionType = Qt::DirectConnection;
- if(QThread::currentThread() != QCoreApplication::instance()->thread())
- {
- connectionType = Qt::BlockingQueuedConnection;
- }
-
- QMetaObject::invokeMethod(guiref, "askFee", connectionType,
+ QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
Q_ARG(qint64, nFeeRequired),
Q_ARG(bool*, &payFee));
if(!guiref)
return;
- // Call slot on GUI thread.
- // If called from another thread, use a blocking QueuedConnection.
- Qt::ConnectionType connectionType = Qt::DirectConnection;
- if(QThread::currentThread() != QCoreApplication::instance()->thread())
- {
- connectionType = Qt::BlockingQueuedConnection;
- }
- QMetaObject::invokeMethod(guiref, "handleURL", connectionType,
+ QMetaObject::invokeMethod(guiref, "handleURL", GUIUtil::blockingGUIThreadConnection(),
Q_ARG(QString, QString::fromStdString(strURL)));
}
-void CalledSetStatusBar(const std::string& strText, int nField)
-{
- // Only used for built-in mining, which is disabled, simple ignore
-}
-
-void UIThreadCall(boost::function0<void> fn)
+void MainFrameRepaint()
{
- // Only used for built-in mining, which is disabled, simple ignore
+ if(clientmodel)
+ QMetaObject::invokeMethod(clientmodel, "update", Qt::QueuedConnection);
+ if(walletmodel)
+ QMetaObject::invokeMethod(walletmodel, "update", Qt::QueuedConnection);
}
-void MainFrameRepaint()
+void AddressBookRepaint()
{
- if(guiref)
- QMetaObject::invokeMethod(guiref, "refreshStatusBar", Qt::QueuedConnection);
+ if(walletmodel)
+ QMetaObject::invokeMethod(walletmodel, "updateAddressList", Qt::QueuedConnection);
}
void InitMessage(const std::string &message)
}
}
+void QueueShutdown()
+{
+ QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
+}
+
/*
Translate string to current locale using Qt.
*/
try
{
+ BitcoinGUI window;
+ guiref = &window;
if(AppInit2(argc, argv))
{
{
- // Put this in a block, so that BitcoinGUI is cleaned up properly before
- // calling Shutdown() in case of exceptions.
+ // Put this in a block, so that the Model objects are cleaned up before
+ // calling Shutdown().
optionsModel.Upgrade(); // Must be done after AppInit2
- BitcoinGUI window;
if (splashref)
splash.finish(&window);
ClientModel clientModel(&optionsModel);
+ clientmodel = &clientModel;
WalletModel walletModel(pwalletMain, &optionsModel);
+ walletmodel = &walletModel;
- guiref = &window;
window.setClientModel(&clientModel);
window.setWalletModel(&walletModel);
#endif
app.exec();
+ window.setClientModel(0);
+ window.setWalletModel(0);
guiref = 0;
+ clientmodel = 0;
+ walletmodel = 0;
}
Shutdown(NULL);
}
connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
// Report errors from network/worker thread
- connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
+ connect(clientModel, SIGNAL(error(QString,QString, bool)), this, SLOT(error(QString,QString,bool)));
}
}
if(walletModel)
{
// Report errors from wallet thread
- connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
+ connect(walletModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool)));
// Put transaction list in tabs
transactionView->setModel(walletModel);
progressBar->setToolTip(tooltip);
}
-void BitcoinGUI::refreshStatusBar()
-{
- /* Might display multiple times in the case of multiple alerts
- static QString prevStatusBar;
- QString newStatusBar = clientModel->getStatusBarWarnings();
- if (prevStatusBar != newStatusBar)
- {
- prevStatusBar = newStatusBar;
- error(tr("Network Alert"), newStatusBar);
- }*/
- setNumBlocks(clientModel->getNumBlocks());
-}
-
-void BitcoinGUI::error(const QString &title, const QString &message)
+void BitcoinGUI::error(const QString &title, const QString &message, bool modal)
{
// Report errors from network/worker thread
- notificator->notify(Notificator::Critical, title, message);
+ if(modal)
+ {
+ QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok);
+ } else {
+ notificator->notify(Notificator::Critical, title, message);
+ }
}
void BitcoinGUI::changeEvent(QEvent *e)
@see WalletModel::EncryptionStatus
*/
void setEncryptionStatus(int status);
- /** Set the status bar text if there are any warnings (removes sync progress bar if applicable) */
- void refreshStatusBar();
/** Notify the user of an error in the network or transaction handling code. */
- void error(const QString &title, const QString &message);
+ void error(const QString &title, const QString &message, bool modal);
/** Asks the user whether to pay the transaction fee or to cancel the transaction.
It is currently not possible to pass a return value to another thread through
BlockingQueuedConnection, so an indirected pointer is used.
#include "headers.h"
-#include <QTimer>
#include <QDateTime>
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
QObject(parent), optionsModel(optionsModel),
cachedNumConnections(0), cachedNumBlocks(0)
{
- // Until signal notifications is built into the bitcoin core,
- // simply update everything after polling using a timer.
- QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(update()));
- timer->start(MODEL_UPDATE_DELAY);
-
numBlocksAtStartup = -1;
}
{
int newNumConnections = getNumConnections();
int newNumBlocks = getNumBlocks();
+ QString newStatusBar = getStatusBarWarnings();
if(cachedNumConnections != newNumConnections)
emit numConnectionsChanged(newNumConnections);
- if(cachedNumBlocks != newNumBlocks)
+ if(cachedNumBlocks != newNumBlocks || cachedStatusBar != newStatusBar)
+ {
+ // Simply emit a numBlocksChanged for now in case the status message changes,
+ // so that the view updates the status bar.
+ // TODO: It should send a notification.
+ // (However, this might generate looped notifications and needs to be thought through and tested carefully)
+ // error(tr("Network Alert"), newStatusBar);
emit numBlocksChanged(newNumBlocks);
+ }
cachedNumConnections = newNumConnections;
cachedNumBlocks = newNumBlocks;
+ cachedStatusBar = newStatusBar;
}
bool ClientModel::isTestNet() const
int cachedNumConnections;
int cachedNumBlocks;
+ QString cachedStatusBar;
int numBlocksAtStartup;
void numBlocksChanged(int count);
//! Asynchronous error notification
- void error(const QString &title, const QString &message);
+ void error(const QString &title, const QString &message, bool modal);
public slots:
#include <QClipboard>
#include <QFileDialog>
#include <QDesktopServices>
+#include <QThread>
QString GUIUtil::dateTimeStr(qint64 nTime)
{
return result;
}
+Qt::ConnectionType GUIUtil::blockingGUIThreadConnection()
+{
+ if(QThread::currentThread() != QCoreApplication::instance()->thread())
+ {
+ return Qt::BlockingQueuedConnection;
+ }
+ else
+ {
+ return Qt::DirectConnection;
+ }
+}
const QString &dir=QString(), const QString &filter=QString(),
QString *selectedSuffixOut=0);
+
+ /** Get connection type to call object slot in GUI thread with invokeMethod. The call will be blocking.
+
+ @returns If called from the GUI thread, return a Qt::DirectConnection.
+ If called from another thread, return a Qt::BlockingQueuedConnection.
+ */
+ static Qt::ConnectionType blockingGUIThreadConnection();
+
};
#endif // GUIUTIL_H
#include "bitcoinunits.h"
#include "headers.h"
-#include "qtui.h"
+#include "ui_interface.h"
#include <QString>
#include "headers.h"
#include "db.h" // for BackupWallet
-#include <QTimer>
#include <QSet>
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0),
cachedEncryptionStatus(Unencrypted)
{
- // Until signal notifications is built into the bitcoin core,
- // simply update everything after polling using a timer.
- QTimer *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(update()));
- timer->start(MODEL_UPDATE_DELAY);
-
addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this);
}
addressTableModel->update();
}
+void WalletModel::updateAddressList()
+{
+ addressTableModel->update();
+}
+
bool WalletModel::validateAddress(const QString &address)
{
CBitcoinAddress addressParsed(address.toStdString());
}
return TransactionCreationFailed;
}
- if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString(), NULL))
+ if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString()))
{
return Aborted;
}
}
}
- // Update our model of the address table
- addressTableModel->updateList();
-
return SendCoinsReturn(OK, 0, hex);
}
#include <QObject>
-#include "util.h"
+#include "allocators.h" /* for SecureString */
class OptionsModel;
class AddressTableModel;
void requireUnlock();
// Asynchronous error notification
- void error(const QString &title, const QString &message);
+ void error(const QString &title, const QString &message, bool modal);
public slots:
-
-private slots:
void update();
+ void updateAddressList();
};
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>
+#include "allocators.h"
+
typedef long long int64;
typedef unsigned long long uint64;
-#ifdef WIN32
-#define _WIN32_WINNT 0x0501
-#define WIN32_LEAN_AND_MEAN 1
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-#include <windows.h>
-// This is used to attempt to keep keying material out of swap
-// Note that VirtualLock does not provide this as a guarantee on Windows,
-// but, in practice, memory that has been VirtualLock'd almost never gets written to
-// the pagefile except in rare circumstances where memory is extremely low.
-#define mlock(p, n) VirtualLock((p), (n));
-#define munlock(p, n) VirtualUnlock((p), (n));
-#else
-#include <sys/mman.h>
-#include <limits.h>
-/* This comes from limits.h if it's not defined there set a sane default */
-#ifndef PAGESIZE
-#include <unistd.h>
-#define PAGESIZE sysconf(_SC_PAGESIZE)
-#endif
-#define mlock(a,b) \
- mlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
- (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
-#define munlock(a,b) \
- munlock(((void *)(((size_t)(a)) & (~((PAGESIZE)-1)))),\
- (((((size_t)(a)) + (b) - 1) | ((PAGESIZE) - 1)) + 1) - (((size_t)(a)) & (~((PAGESIZE) - 1))))
-#endif
-
class CScript;
class CDataStream;
class CAutoFile;
-//
-// Allocator that locks its contents from being paged
-// out of memory and clears its contents before deletion.
-//
-template<typename T>
-struct secure_allocator : public std::allocator<T>
-{
- // MSVC8 default copy constructor is broken
- typedef std::allocator<T> base;
- typedef typename base::size_type size_type;
- typedef typename base::difference_type difference_type;
- typedef typename base::pointer pointer;
- typedef typename base::const_pointer const_pointer;
- typedef typename base::reference reference;
- typedef typename base::const_reference const_reference;
- typedef typename base::value_type value_type;
- secure_allocator() throw() {}
- secure_allocator(const secure_allocator& a) throw() : base(a) {}
- template <typename U>
- secure_allocator(const secure_allocator<U>& a) throw() : base(a) {}
- ~secure_allocator() throw() {}
- template<typename _Other> struct rebind
- { typedef secure_allocator<_Other> other; };
-
- T* allocate(std::size_t n, const void *hint = 0)
- {
- T *p;
- p = std::allocator<T>::allocate(n, hint);
- if (p != NULL)
- mlock(p, sizeof(T) * n);
- return p;
- }
-
- void deallocate(T* p, std::size_t n)
- {
- if (p != NULL)
- {
- memset(p, 0, sizeof(T) * n);
- munlock(p, sizeof(T) * n);
- }
- std::allocator<T>::deallocate(p, n);
- }
-};
-
-
-//
-// Allocator that clears its contents before deletion.
-//
-template<typename T>
-struct zero_after_free_allocator : public std::allocator<T>
-{
- // MSVC8 default copy constructor is broken
- typedef std::allocator<T> base;
- typedef typename base::size_type size_type;
- typedef typename base::difference_type difference_type;
- typedef typename base::pointer pointer;
- typedef typename base::const_pointer const_pointer;
- typedef typename base::reference reference;
- typedef typename base::const_reference const_reference;
- typedef typename base::value_type value_type;
- zero_after_free_allocator() throw() {}
- zero_after_free_allocator(const zero_after_free_allocator& a) throw() : base(a) {}
- template <typename U>
- zero_after_free_allocator(const zero_after_free_allocator<U>& a) throw() : base(a) {}
- ~zero_after_free_allocator() throw() {}
- template<typename _Other> struct rebind
- { typedef zero_after_free_allocator<_Other> other; };
-
- void deallocate(T* p, std::size_t n)
- {
- if (p != NULL)
- memset(p, 0, sizeof(T) * n);
- std::allocator<T>::deallocate(p, n);
- }
-};
// Copyright (c) 2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_EXTERNUI_H
-#define BITCOIN_EXTERNUI_H
+#ifndef BITCOIN_UI_INTERFACE_H
+#define BITCOIN_UI_INTERFACE_H
#include <string>
-#include <boost/function/function0.hpp>
-#include "wallet.h"
+#include "util.h" // for int64
-typedef void wxWindow;
#define wxYES 0x00000002
#define wxOK 0x00000004
#define wxNO 0x00000008
#define wxHELP 0x00008000
#define wxMORE 0x00010000
#define wxSETUP 0x00020000
+// Force blocking, modal message box dialog (not just notification)
+#define wxMODAL 0x00040000
-extern int MyMessageBox(const std::string& message, const std::string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);
-#define wxMessageBox MyMessageBox
-extern int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);
-extern bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent);
+/* These UI communication functions are implemented in bitcoin.cpp (for ui) and noui.cpp (no ui) */
+
+extern int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK);
+extern bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption);
extern void ThreadSafeHandleURL(const std::string& strURL);
-extern void CalledSetStatusBar(const std::string& strText, int nField);
-extern void UIThreadCall(boost::function0<void> fn);
extern void MainFrameRepaint();
+extern void AddressBookRepaint();
+extern void QueueShutdown();
extern void InitMessage(const std::string &message);
extern std::string _(const char* psz);
string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
- boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
+ ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION);
}
}
}
}
#endif
-#if !defined(QT_GUI)
-inline const char* _(const char* psz)
-{
- return psz;
-}
-#endif
-
-
-
-// This is exactly like std::string, but with a custom allocator.
-// (secure_allocator<> is defined in serialize.h)
-typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString;
-
-
-
-
-
inline std::string i64tostr(int64 n)
{
return strprintf("%"PRI64d, n);
return strError;
}
- if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
+ if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending...")))
return "ABORTED";
if (!CommitTransaction(wtxNew, reservekey))
bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
{
mapAddressBook[address] = strName;
+ AddressBookRepaint();
if (!fFileBacked)
return false;
return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
{
mapAddressBook.erase(address);
+ AddressBookRepaint();
if (!fFileBacked)
return false;
return CWalletDB(strWalletFile).EraseName(address.ToString());