Merge pull request #1019 from laanwj/2012_03_uirefactor
authorPieter Wuille <pieter.wuille@gmail.com>
Wed, 4 Apr 2012 12:03:07 +0000 (05:03 -0700)
committerPieter Wuille <pieter.wuille@gmail.com>
Wed, 4 Apr 2012 12:03:07 +0000 (05:03 -0700)
Streamline UI ↔ Core interface

31 files changed:
bitcoin-qt.pro
src/allocators.h [new file with mode: 0644]
src/bitcoinrpc.cpp
src/crypter.h
src/headers.h
src/init.cpp
src/main.cpp
src/makefile.linux-mingw
src/makefile.mingw
src/makefile.osx
src/makefile.unix
src/noui.cpp [new file with mode: 0644]
src/noui.h [deleted file]
src/qt/addressbookpage.cpp
src/qt/addresstablemodel.cpp
src/qt/addresstablemodel.h
src/qt/bitcoin.cpp
src/qt/bitcoingui.cpp
src/qt/bitcoingui.h
src/qt/clientmodel.cpp
src/qt/clientmodel.h
src/qt/guiutil.cpp
src/qt/guiutil.h
src/qt/transactiondesc.cpp
src/qt/walletmodel.cpp
src/qt/walletmodel.h
src/serialize.h
src/ui_interface.h [moved from src/qtui.h with 75% similarity]
src/util.cpp
src/util.h
src/wallet.cpp

index d9206b3..7ad9403 100644 (file)
@@ -115,7 +115,6 @@ HEADERS += src/qt/bitcoingui.h \
     src/key.h \
     src/db.h \
     src/script.h \
-    src/noui.h \
     src/init.h \
     src/headers.h \
     src/irc.h \
@@ -135,7 +134,6 @@ HEADERS += src/qt/bitcoingui.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 \
@@ -155,7 +153,9 @@ HEADERS += src/qt/bitcoingui.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 \
diff --git a/src/allocators.h b/src/allocators.h
new file mode 100644 (file)
index 0000000..85d9cfb
--- /dev/null
@@ -0,0 +1,119 @@
+// 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
index 868419e..eb2f04f 100644 (file)
@@ -221,13 +221,9 @@ Value stop(const Array& params, bool fHelp)
         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
 }
 
 
@@ -1676,11 +1672,6 @@ Value encryptwallet(const Array& params, bool fHelp)
     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;
@@ -1698,7 +1689,7 @@ Value encryptwallet(const Array& params, bool fHelp)
     // 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";
 }
 
@@ -2371,19 +2362,18 @@ void ThreadRPCServer2(void* parg)
             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;
     }
 
index 0f9ea02..59a005a 100644 (file)
@@ -4,7 +4,7 @@
 #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;
index 3596fd0..ceee028 100644 (file)
@@ -87,8 +87,5 @@
 #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"
index 8531b20..eecbc83 100644 (file)
 #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
@@ -248,7 +237,7 @@ bool AppInit2(int argc, char* argv[])
         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
@@ -337,7 +326,7 @@ bool AppInit2(int argc, char* argv[])
     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;
     }
 
@@ -379,7 +368,7 @@ bool AppInit2(int argc, char* argv[])
         {
             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
@@ -451,7 +440,7 @@ bool AppInit2(int argc, char* argv[])
 
     if (!strErrors.str().empty())
     {
-        wxMessageBox(strErrors.str(), "Bitcoin", wxOK | wxICON_ERROR);
+        ThreadSafeMessageBox(strErrors.str(), _("Bitcoin"), wxOK | wxICON_ERROR | wxMODAL);
         return false;
     }
 
@@ -507,7 +496,7 @@ bool AppInit2(int argc, char* argv[])
         addrProxy = CService(mapArgs["-proxy"], 9050);
         if (!addrProxy.IsValid())
         {
-            wxMessageBox(_("Invalid -proxy address"), "Bitcoin");
+            ThreadSafeMessageBox(_("Invalid -proxy address"), _("Bitcoin"), wxOK | wxMODAL);
             return false;
         }
     }
@@ -538,7 +527,7 @@ bool AppInit2(int argc, char* argv[])
         std::string strError;
         if (!BindListenPort(strError))
         {
-            wxMessageBox(strError, "Bitcoin");
+            ThreadSafeMessageBox(strError, _("Bitcoin"), wxOK | wxMODAL);
             return false;
         }
     }
@@ -558,11 +547,11 @@ bool AppInit2(int argc, char* argv[])
     {
         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);
     }
 
     //
@@ -574,7 +563,7 @@ bool AppInit2(int argc, char* argv[])
     RandAddSeedPerfmon();
 
     if (!CreateThread(StartNode, NULL))
-        wxMessageBox(_("Error: CreateThread(StartNode) failed"), "Bitcoin");
+        ThreadSafeMessageBox(_("Error: CreateThread(StartNode) failed"), _("Bitcoin"), wxOK | wxMODAL);
 
     if (fServer)
         CreateThread(ThreadRPCServer, NULL);
index ca75b9f..7c49316 100644 (file)
@@ -1811,8 +1811,8 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
         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;
@@ -3450,8 +3450,6 @@ void static BitcoinMiner(CWallet *pwallet)
                         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)
                         {
@@ -3508,7 +3506,6 @@ void static ThreadBitcoinMiner(void* parg)
         vnThreadsRunning[THREAD_MINER]--;
         PrintException(NULL, "ThreadBitcoinMiner()");
     }
-    UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
     nHPSTimerStart = 0;
     if (vnThreadsRunning[THREAD_MINER] == 0)
         dHashesPerSec = 0;
index 40ce1dc..0bbe612 100644 (file)
@@ -59,7 +59,8 @@ OBJS= \
     obj/rpcdump.o \
     obj/script.o \
     obj/util.o \
-    obj/wallet.o
+    obj/wallet.o \
+    obj/noui.o
 
 all: bitcoind.exe
 
index f7dfcc7..307fca7 100644 (file)
@@ -57,7 +57,8 @@ OBJS= \
     obj/rpcdump.o \
     obj/script.o \
     obj/util.o \
-    obj/wallet.o
+    obj/wallet.o \
+    obj/noui.o
 
 
 all: bitcoind.exe
index 8790d92..6388a71 100644 (file)
@@ -74,7 +74,8 @@ OBJS= \
     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)
index 92c1b97..66e020b 100644 (file)
@@ -105,7 +105,8 @@ OBJS= \
     obj/rpcdump.o \
     obj/script.o \
     obj/util.o \
-    obj/wallet.o
+    obj/wallet.o \
+    obj/noui.o
 
 
 all: bitcoind
diff --git a/src/noui.cpp b/src/noui.cpp
new file mode 100644 (file)
index 0000000..077e460
--- /dev/null
@@ -0,0 +1,45 @@
+// 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);
+}
+
diff --git a/src/noui.h b/src/noui.h
deleted file mode 100644 (file)
index 458fc64..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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
index cb185be..8821283 100644 (file)
@@ -94,8 +94,6 @@ void AddressBookPage::setModel(AddressTableModel *model)
     this->model = model;
     if(!model)
         return;
-    // Refresh list from core
-    model->updateList();
 
     proxyModel = new QSortFilterProxyModel(this);
     proxyModel->setSourceModel(model);
index 8fd6d52..198a857 100644 (file)
@@ -231,7 +231,7 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & pa
     }
 }
 
-void AddressTableModel::updateList()
+void AddressTableModel::update()
 {
     // Update address book model from Bitcoin core
     beginResetModel();
@@ -285,10 +285,9 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
     {
         return QString();
     }
-    // Add entry and update list
+    // Add entry
     CRITICAL_BLOCK(wallet->cs_wallet)
         wallet->SetAddressBookName(strAddress, strLabel);
-    updateList();
     return QString::fromStdString(strAddress);
 }
 
@@ -306,15 +305,9 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex & paren
     {
         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
index 0743300..7fd07cf 100644 (file)
@@ -56,10 +56,6 @@ public:
      */
     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;
@@ -82,6 +78,8 @@ signals:
     void defaultAddressChanged(const QString &address);
 
 public slots:
+    /* Update address list from core. Invalidates any indices.
+     */
     void update();
 };
 
index 6ee7fed..394e4a7 100644 (file)
@@ -5,6 +5,7 @@
 #include "clientmodel.h"
 #include "walletmodel.h"
 #include "optionsmodel.h"
+#include "guiutil.h"
 
 #include "headers.h"
 #include "init.h"
@@ -12,7 +13,6 @@
 
 #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
     {
@@ -51,7 +59,7 @@ int ThreadSafeMessageBox(const std::string& message, const std::string& caption,
     return 4;
 }
 
-bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent)
+bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption)
 {
     if(!guiref)
         return false;
@@ -59,15 +67,7 @@ bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindo
         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));
 
@@ -79,31 +79,22 @@ void ThreadSafeHandleURL(const std::string& strURL)
     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)
@@ -115,6 +106,11 @@ void InitMessage(const std::string &message)
     }
 }
 
+void QueueShutdown()
+{
+    QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
+}
+
 /*
    Translate string to current locale using Qt.
  */
@@ -221,22 +217,24 @@ int main(int argc, char *argv[])
 
     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);
 
@@ -273,7 +271,11 @@ int main(int argc, char *argv[])
 #endif
                 app.exec();
 
+                window.setClientModel(0);
+                window.setWalletModel(0);
                 guiref = 0;
+                clientmodel = 0;
+                walletmodel = 0;
             }
             Shutdown(NULL);
         }
index 00bb5bd..a60b585 100644 (file)
@@ -339,7 +339,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
         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)));
     }
 }
 
@@ -349,7 +349,7 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel)
     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);
@@ -552,23 +552,15 @@ void BitcoinGUI::setNumBlocks(int count)
     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)
index dbc3264..c684d7c 100644 (file)
@@ -113,11 +113,9 @@ public slots:
        @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.
index 5a0b4aa..8163da0 100644 (file)
@@ -6,19 +6,12 @@
 
 #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;
 }
 
@@ -47,14 +40,23 @@ void ClientModel::update()
 {
     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
index 5a12c4f..6366b4d 100644 (file)
@@ -43,6 +43,7 @@ private:
 
     int cachedNumConnections;
     int cachedNumBlocks;
+    QString cachedStatusBar;
 
     int numBlocksAtStartup;
 
@@ -51,7 +52,7 @@ signals:
     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:
 
index ac69bd0..ad530a7 100644 (file)
@@ -17,6 +17,7 @@
 #include <QClipboard>
 #include <QFileDialog>
 #include <QDesktopServices>
+#include <QThread>
 
 QString GUIUtil::dateTimeStr(qint64 nTime)
 {
@@ -184,3 +185,14 @@ QString GUIUtil::getSaveFileName(QWidget *parent, const QString &caption,
     return result;
 }
 
+Qt::ConnectionType GUIUtil::blockingGUIThreadConnection()
+{
+    if(QThread::currentThread() != QCoreApplication::instance()->thread())
+    {
+        return Qt::BlockingQueuedConnection;
+    }
+    else
+    {
+        return Qt::DirectConnection;
+    }
+}
index 75ba53f..06426d7 100644 (file)
@@ -60,6 +60,14 @@ public:
                                    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
index 4cb2e68..c32a006 100644 (file)
@@ -4,7 +4,7 @@
 #include "bitcoinunits.h"
 
 #include "headers.h"
-#include "qtui.h"
+#include "ui_interface.h"
 
 #include <QString>
 
index 8344a65..6cc0237 100644 (file)
@@ -7,7 +7,6 @@
 #include "headers.h"
 #include "db.h" // for BackupWallet
 
-#include <QTimer>
 #include <QSet>
 
 WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
@@ -16,12 +15,6 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p
     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);
 }
@@ -69,6 +62,11 @@ void WalletModel::update()
     addressTableModel->update();
 }
 
+void WalletModel::updateAddressList()
+{
+    addressTableModel->update();
+}
+
 bool WalletModel::validateAddress(const QString &address)
 {
     CBitcoinAddress addressParsed(address.toStdString());
@@ -142,7 +140,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
             }
             return TransactionCreationFailed;
         }
-        if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString(), NULL))
+        if(!ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString()))
         {
             return Aborted;
         }
@@ -164,9 +162,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipie
         }
     }
 
-    // Update our model of the address table
-    addressTableModel->updateList();
-
     return SendCoinsReturn(OK, 0, hex);
 }
 
index e894842..c446817 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <QObject>
 
-#include "util.h"
+#include "allocators.h" /* for SecureString */
 
 class OptionsModel;
 class AddressTableModel;
@@ -135,12 +135,11 @@ signals:
     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();
 };
 
 
index 227bfb9..2d4aaba 100644 (file)
 #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;
@@ -779,81 +752,6 @@ struct ser_streamplaceholder
 
 
 
-//
-// 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);
-    }
-};
 
 
 
similarity index 75%
rename from src/qtui.h
rename to src/ui_interface.h
index 9791ba5..2e29f2a 100644 (file)
@@ -1,14 +1,12 @@
 // 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
@@ -35,15 +33,17 @@ typedef void wxWindow;
 #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);
 
index cf73ecf..4f34ab6 100644 (file)
@@ -1041,7 +1041,7 @@ void AddTimeData(const CNetAddr& ip, int64 nTime)
                     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);
                 }
             }
         }
index 0af5b0a..e4cf83f 100644 (file)
@@ -95,13 +95,6 @@ inline void Sleep(int64 n)
 }
 #endif
 
-#if !defined(QT_GUI)
-inline const char* _(const char* psz)
-{
-    return psz;
-}
-#endif
-
 
 
 
@@ -267,16 +260,6 @@ public:
 
 
 
-
-
-// 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);
index 27ed722..e444e5f 100644 (file)
@@ -1219,7 +1219,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew,
         return strError;
     }
 
-    if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
+    if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending...")))
         return "ABORTED";
 
     if (!CommitTransaction(wtxNew, reservekey))
@@ -1279,6 +1279,7 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
 {
     mapAddressBook[address] = strName;
+    AddressBookRepaint();
     if (!fFileBacked)
         return false;
     return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
@@ -1287,6 +1288,7 @@ bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& s
 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
 {
     mapAddressBook.erase(address);
+    AddressBookRepaint();
     if (!fFileBacked)
         return false;
     return CWalletDB(strWalletFile).EraseName(address.ToString());